What is the Bit Manipulation Technique?
Bit Manipulation is a technique in DSA where we use binary representations of given data and binary operations to solve problems efficiently.
Bit Manipulation is a technique in DSA where we use binary representations of given data and binary operations to solve problems efficiently.
Let’s break down the number 57 into its binary form and explain it using powers of two.
In binary, 57 is represented as:
To understand how numbers are represented in binary, let’s take the decimal number 57 and convert it into binary step by step.
We start by finding the highest power of 2 less than or equal to 57. That’s 2⁵ = 32.
Now subtract:
57 - 32 = 25
The next largest power of 2 that fits into 25 is 2⁴ = 16:
25 - 16 = 9
Then 2³ = 8 fits into 9:
9 - 8 = 1
Finally, 2⁰ = 1 fits into 1:
1 - 1 = 0
So, we can say:
57 = 2⁵ + 2⁴ + 2³ + 2⁰ = 32 + 16 + 8 + 1
Binary digits (bits) represent powers of two from right to left:
Bit Position
Power of 2:
Used in 57?:
This gives us the binary representation of 57:
| Decimal | Binary |
|---|---|
| 1 | 00000001 |
| 2 | 00000010 |
| 3 | 00000011 |
| 4 | 00000100 |
| 5 | 00000101 |
| 6 | 00000110 |
| 7 | 00000111 |
| 8 | 00001000 |
| 9 | 00001001 |
| 10 | 00001010 |
| 11 | 00001011 |
| 12 | 00001100 |
| 13 | 00001101 |
| 14 | 00001110 |
| 15 | 00001111 |
| 16 | 00010000 |
| 17 | 00010001 |
| 18 | 00010010 |
| 19 | 00010011 |
| 20 | 00010100 |
The most common way to check if a number is even is by using the modulus operator:
if num % 2 == 0:
print("Even")
else:
print("Odd")
This checks if the remainder when the number is divided by 2 is zero. If true, the number is even.
An optimized way to check if a number is even is to use a bitwise AND operation:
if (num & 1) == 0:
print("Even")
else:
print("Odd")
This works because in binary, all even numbers have a least significant bit (LSB) of 0, and odd numbers have LSB of 1.
The expression num & 1 isolates the LSB:
num % 2 to check if a number is even, the computer has to perform a division operation to find the remainder. Division takes more steps for the computer to complete, especially compared to simpler operations.
num & 1 work directly on the binary form of the number. These operations are handled at a very low level by the computer — they usually take just one quick step, making them much faster than division.
% is like using a calculator to divide by 2 every time. Using & is like glancing at the last digit in binary — it’s instant and efficient.
num % 2 = Slower (involves division)num & 1 = Faster (uses binary and needs just one quick step)LSB = 0 → 6 is Even
LSB = 1 → 7 is Odd
Therefore, using num & 1 is a faster and more efficient method to check for even or odd numbers,
especially when performing large-scale or repeated computations.
num & 1 returns 0 if even, 1 if odd.
a = a ^ b; b = a ^ b; a = a ^ b;
(num & (num - 1)) == 0 for num > 0
Brian Kernighan’s algorithm.
num ^ (1 << i) toggles the ith bit.
num | (1 << i)num & ~(1 << i)
num << k → equivalent to num * 2knum >> k → equivalent to num / 2k
n elements, use integers from 0 to 2n - 1 as masks to generate all subsets.
As a beginner, look for the following clues in a problem:
^) is your friend here.
*, /, %.
Bit Manipulation techniques rely heavily on bitwise operators. These operators work at the binary level and are extremely useful for efficient computations, especially in low-level or performance-critical programming. Understanding each operator helps you apply them effectively.
The & operator compares each bit of two numbers and returns 1 only if both bits are 1. Otherwise, it returns 0.
a = 5 # Binary: 0101
b = 3 # Binary: 0011
result = a & b # 0001 → 1
The | operator compares each bit of two numbers and returns 1 if either of the bits is 1.
a = 5 # Binary: 0101
b = 3 # Binary: 0011
result = a | b # 0111 → 7
The ^ operator (exclusive OR) returns 1 if the bits are different, and 0 if they are the same.
It's often used to toggle bits or find unique elements.
a = 5 # Binary: 0101
b = 3 # Binary: 0011
result = a ^ b # 0110 → 6
The ~ operator inverts each bit of the number — 0s become 1s, and 1s become 0s.
It effectively returns the negative value of the number minus one (i.e., ~n = -n - 1).
a = 5 # Binary: 00000101
result = ~a # 11111010 → -6
The << operator shifts all bits to the left by a given number of positions.
Each shift multiplies the number by 2.
a = 5 # Binary: 00000101
result = a << 1 # 00001010 → 10 (5 × 2)
result = a << 2 # 00010100 → 20 (5 × 4)
The >> operator shifts all bits to the right by a given number of positions.
Each shift divides the number by 2 (discarding the remainder).
a = 5 # Binary: 00000101
result = a >> 1 # 00000010 → 2 (5 // 2)
result = a >> 2 # 00000001 → 1 (5 // 4)
| Operator | Name | Description |
|---|---|---|
| & | AND | 1 if both bits are 1 |
| | | OR | 1 if either bit is 1 |
| ^ | XOR | 1 if bits are different |
| ~ | NOT | Inverts all bits |
| << | Left Shift | Shifts bits left (×2 per shift) |
| >> | Right Shift | Shifts bits right (÷2 per shift) |
To determine if a number is a power of two using bit manipulation, we rely on the fact that powers of two have a very unique pattern in binary:
0001001001001000Notice a pattern? Every power of two has exactly one bit set to 1 and all other bits are 0.
This is the key to our trick: if a number n is a power of two, then n has exactly one set bit. And here’s what happens when you subtract 1 from such a number:
n = 8 (binary = 1000)n - 1 = 7 (binary = 0111)Now, let’s perform a bitwise AND between n and n - 1:
1000 (8)
& 0111 (7)
= 0000
The result is 0. This will only happen for numbers that are powers of two.
n is greater than 0 (since 0 and negatives are not powers of 2).n & (n - 1)n is a power of 2. Otherwise, it’s not.Bit manipulation provides an incredibly fast and elegant solution here. Instead of looping or dividing repeatedly to check powers of 2, we do just one & operation:
This is far more efficient than traditional methods like looping, especially for performance-critical applications like embedded systems, competitive programming, and large-scale simulations.
// Pseudocode
function isPowerOfTwo(n):
return n > 0 and (n & (n - 1)) == 0
n = 16 → binary = 10000 → n & (n-1) = 10000 & 01111 = 0 → Power of 2n = 18 → binary = 10010 → n & (n-1) ≠ 0 → ❌ Not a power of 2Note: This method only works for positive integers. If n ≤ 0, it's not a power of 2.
Bit Manipulation is an efficient and low-level technique in DSA. It is particularly useful when solving problems related to flags, parity, and optimization. Mastering bit operations can lead to elegant and performant solutions for a variety of tricky problems.