Bit manipulation is the art of solving problems by operating directly on the binary representation of numbers.
It is fast, memory-efficient, and frequently tested in top product company interviews.
If a problem involves:
Think in bits.
Every integer is stored in binary (base-2).
Example:
Decimal 5 → 101
Decimal 10 → 1010
Decimal 12 → 1100
Each position represents a power of 2.
Most languages use 2’s complement:
Understanding this helps with edge cases.
1 & 1 = 1
1 & 0 = 0
Used for:
Example:
if((x & 1) == 1) // odd number
1 | 0 = 1
Used for:
x = x | (1 << i);
1 ^ 1 = 0
1 ^ 0 = 1
Key property:
Same bits cancel each other
a ^ a = 0
a ^ 0 = a
Flips all bits.
~5 → -(5+1) = -6
Multiply by powers of 2.
5 << 1 → 10
Divide by powers of 2.
10 >> 1 → 5
XOR is associative and commutative.
a ^ b ^ a = b
Used heavily in:
Every number appears twice except one.
int ans = 0;
for(int x : arr)
ans ^= x;
Why it works:
Time: O(n)
Space: O(1)
Every number appears three times except one.
Approach:
int result = 0;
for(int i = 0; i < 32; i++){
int sum = 0;
for(int x : arr){
if((x & (1 << i)) != 0)
sum++;
}
if(sum % 3 != 0)
result |= (1 << i);
}
Each iteration removes the lowest set bit.
int count = 0;
while(n > 0){
n = n & (n - 1);
count++;
}
Time: O(number of set bits)
Integer.bitCount(n);
A number is power of two if:
boolean isPowerOfTwo(int n){
return n > 0 && (n & (n - 1)) == 0;
}
Examples:
For a set of size n:
Example:
[1, 2, 3]
000 → []
001 → [1]
010 → [2]
011 → [1,2]
100 → [3]
for(int mask = 0; mask < (1 << n); mask++){
for(int i = 0; i < n; i++){
if((mask & (1 << i)) != 0)
System.out.print(arr[i]);
}
}
Used in:
(x & (1 << i)) != 0
x = x | (1 << i);
x = x & ~(1 << i);
x = x ^ (1 << i);
int lsb = n & (-n);
Used in:
a = a ^ b;
b = a ^ b;
a = a ^ b;
if((n & 1) == 1) // odd
n << 1
n >> 1
Use when:
Avoid when: