Skip to main content

Bit Manipulation & Advanced Topics


Bit Manipulation

Work directly with binary representations for ultra-fast, space-efficient solutions.

Bitwise Operators

OperatorSymbolEffectExample
AND&1 only if both 15 & 3 = 1 (101 & 011 = 001)
OR|1 if either 15 | 3 = 7 (101 | 011 = 111)
XOR^1 if different5 ^ 3 = 6 (101 ^ 011 = 110)
NOT~Flip all bits~5 = -6
Left Shift<<Multiply by 2ⁿ5 << 1 = 10
Right Shift>>Divide by 2ⁿ20 >> 2 = 5

Essential Bit Tricks

// C++
int n = 13; // binary: 1101

// Check if bit i is set
bool isBitSet(int n, int i) { return (n >> i) & 1; }

// Set bit i
int setBit(int n, int i) { return n | (1 << i); }

// Clear bit i
int clearBit(int n, int i) { return n & ~(1 << i); }

// Toggle bit i
int toggleBit(int n, int i){ return n ^ (1 << i); }

// Check even/odd
bool isOdd(int n) { return n & 1; }

// Check power of 2
bool isPowerOf2(int n) { return n > 0 && (n & (n - 1)) == 0; }
// n=8 (1000), n-1=7 (0111), 8&7 = 0 → true

// Count set bits (popcount)
int countSetBits(int n) {
int count = 0;
while (n) { count += n & 1; n >>= 1; }
return count;
}
// Built-in C++: __builtin_popcount(n)

// Turn off rightmost set bit
int turnOffRight(int n) { return n & (n - 1); }

// Lowest set bit
int lowestSetBit(int n) { return n & (-n); }

Single Number — XOR Magic

XOR of a number with itself = 0. XOR of 0 with x = x.

Pattern trigger: "Single number", "find unique", "all others appear twice"

// C++: Find the one number appearing once
int singleNumber(vector<int>& nums) {
int result = 0;
for (int n : nums) result ^= n; // all pairs cancel out
return result;
}
// Input: [4,1,2,1,2] → Output: 4

Subsets via Bitmask

Generate all subsets of n elements using bits.

// C++: All subsets of [1,2,3]
void generateSubsets(vector<int>& nums) {
int n = nums.size();
for (int mask = 0; mask < (1 << n); mask++) {
cout << "{ ";
for (int i = 0; i < n; i++) {
if (mask & (1 << i))
cout << nums[i] << " ";
}
cout << "}\n";
}
}
// 3 elements → 2³=8 subsets: {},{1},{2},{1,2},{3},{1,3},{2,3},{1,2,3}

Number of 1 Bits (Hamming Weight)

// C++
int hammingWeight(uint32_t n) {
int count = 0;
while (n) {
n &= (n - 1); // clear lowest set bit
count++;
}
return count;
}
// n=11 (1011) → 3 set bits

Advanced Topics

Segment Tree — Range Query & Point Update

Use: Range sum/min/max query + point update in O(log n).

// C++: Segment Tree for range sum
class SegmentTree {
vector<int> tree;
int n;
public:
SegmentTree(vector<int>& arr) {
n = arr.size();
tree.resize(4 * n, 0);
build(arr, 0, 0, n - 1);
}

void build(vector<int>& arr, int node, int start, int end) {
if (start == end) { tree[node] = arr[start]; return; }
int mid = (start + end) / 2;
build(arr, 2*node+1, start, mid);
build(arr, 2*node+2, mid+1, end);
tree[node] = tree[2*node+1] + tree[2*node+2];
}

void update(int node, int start, int end, int idx, int val) {
if (start == end) { tree[node] = val; return; }
int mid = (start + end) / 2;
if (idx <= mid) update(2*node+1, start, mid, idx, val);
else update(2*node+2, mid+1, end, idx, val);
tree[node] = tree[2*node+1] + tree[2*node+2];
}

int query(int node, int start, int end, int l, int r) {
if (r < start || end < l) return 0; // out of range
if (l <= start && end <= r) return tree[node]; // fully in range
int mid = (start + end) / 2;
return query(2*node+1, start, mid, l, r) +
query(2*node+2, mid+1, end, l, r);
}

void update(int idx, int val) { update(0, 0, n-1, idx, val); }
int query(int l, int r) { return query(0, 0, n-1, l, r); }
};

Fenwick Tree (BIT) — Prefix Sum Queries

Simpler than segment tree for prefix sum queries + point updates in O(log n).

// C++
class FenwickTree {
vector<int> bit;
int n;
public:
FenwickTree(int n) : n(n), bit(n + 1, 0) {}

void update(int i, int delta) { // 1-indexed
for (; i <= n; i += i & (-i))
bit[i] += delta;
}

int query(int i) { // prefix sum [1..i]
int sum = 0;
for (; i > 0; i -= i & (-i))
sum += bit[i];
return sum;
}

int rangeQuery(int l, int r) { // [l..r]
return query(r) - query(l - 1);
}
};

Bit Manipulation Patterns

ProblemBit Trick
Find single numberXOR all elements
Power of 2 checkn & (n-1) == 0
Count set bitsn &= n-1 repeatedly
All subsetsBitmask from 0 to 2ⁿ-1
Swap without tempa ^= b; b ^= a; a ^= b
Multiply/divide by 2Left/right shift
Isolate lowest set bitn & (-n)

Comparison: Advanced Structures

StructureQueryUpdateSpaceUse Case
Prefix ArrayO(1)O(n) rebuildO(n)Static array, no updates
Fenwick TreeO(log n)O(log n)O(n)Point update + prefix sum
Segment TreeO(log n)O(log n)O(4n)Range query + range update

Classic Problems

ProblemTechnique
Single NumberXOR
Counting BitsDP + bit tricks
Reverse BitsBit manipulation
Number of 1 BitsBrian Kernighan's trick
All subsetsBitmask DP
Range Sum Query (mutable)Fenwick / Segment Tree
Count of Smaller NumbersFenwick Tree