Bit manipulation techniques - Time & Space Complexity
Bit manipulation techniques use operations on bits to solve problems efficiently.
We want to know how the time needed changes as the number of bits grows.
Analyze the time complexity of the following code snippet.
unsigned int countSetBits(unsigned int n) {
unsigned int count = 0;
while (n) {
count += n & 1;
n >>= 1;
}
return count;
}
This code counts how many bits are set to 1 in the number n.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that checks each bit of n.
- How many times: Once for each bit until n becomes zero.
Explain the growth pattern intuitively.
| Input Size (bits in n) | Approx. Operations |
|---|---|
| 10 | About 10 checks |
| 32 | About 32 checks |
| 64 | About 64 checks |
Pattern observation: The number of operations grows linearly with the number of bits in n.
Time Complexity: O(k) where k is the number of bits in the input number.
This means the time grows directly with how many bits the number has.
[X] Wrong: "Bit operations always run in constant time no matter the number size."
[OK] Correct: Each bit operation is fast, but if you check every bit one by one, the total time depends on how many bits there are.
Understanding bit manipulation time helps you explain why some solutions are fast and others slow, a useful skill in interviews.
"What if we used a built-in function that counts bits in constant time? How would the time complexity change?"
Practice
& do when applied between two bits?Solution
Step 1: Understand bitwise AND operation
The bitwise AND operator compares each bit of two numbers and returns 1 only if both bits are 1.Step 2: Apply to bits
For example, 1 & 1 = 1, but 1 & 0 = 0 and 0 & 0 = 0.Final Answer:
Returns 1 only if both bits are 1 -> Option DQuick Check:
AND = 1 if both bits 1 [OK]
- Confusing AND with OR operator
- Thinking AND flips bits
- Assuming AND always returns 1
num in C?Solution
Step 1: Understand setting a bit
To set a bit means to make it 1 without changing other bits. We use OR with a mask that has 1 at the target bit.Step 2: Use bit shift and OR
The mask is created by shifting 1 left by 3 (1 << 3). OR-ing num with this mask sets the 3rd bit.Final Answer:
num = num | (1 << 3); -> Option AQuick Check:
Set bit = OR with shifted 1 [OK]
- Using AND instead of OR to set bits
- Using XOR which toggles bits
- Shifting num instead of 1
unsigned int x = 5; // binary 0101
x = x ^ (1 << 2);
printf("%u", x);Solution
Step 1: Understand initial value and mask
x = 5 in binary is 0101. The mask is (1 << 2) = 0100 (decimal 4).Step 2: Apply XOR operation
XOR toggles bits where mask has 1. 0101 ^ 0100 = 1101 (decimal 7). Let's do bitwise XOR:
Bits (3 2 1 0):
5 = 0 1 0 1
Mask = 0 1 0 0
XOR = 0 0 0 1 is incorrect.
Actually, bits are:
Bit 3: 0 ^ 0 = 0
Bit 2: 1 ^ 1 = 0
Bit 1: 0 ^ 0 = 0
Bit 0: 1 ^ 0 = 1
Result: 0001 (decimal 1) is incorrect for toggling bit 2.
Wait, bit 2 is the third bit from right (0-indexed). So bits are:
Bit 0: least significant bit
Bit 1: next
Bit 2: next
So 5 (0101) bits:
Bit 3: 0
Bit 2: 1
Bit 1: 0
Bit 0: 1
XOR with mask 0100:
Bit 3: 0 ^ 0 = 0
Bit 2: 1 ^ 1 = 0
Bit 1: 0 ^ 0 = 0
Bit 0: 1 ^ 0 = 1
Result: 0001 (decimal 1). So output is 1.
Therefore, correct answer is 1 -> 1.Final Answer:
1 -> Option BQuick Check:
XOR toggles bit 2: 5 ^ 4 = 1 [OK]
- Miscounting bit positions (0-indexed from right)
- Confusing XOR with OR or AND
- Incorrect binary to decimal conversion
num:unsigned int num = 14; // binary 1110
num = num & (1 << 1);
printf("%u", num);Solution
Step 1: Understand clearing a bit
To clear a bit, we AND with a mask that has 0 at the target bit and 1s elsewhere.Step 2: Analyze given mask
The mask (1 << 1) is 00010 (binary), which has 1 only at bit 1. AND-ing num with this mask keeps only bit 1 and clears others, not what we want.Step 3: Correct mask usage
We should invert the mask: ~ (1 << 1), so bit 1 is 0 and others 1, then AND with num to clear bit 1.Final Answer:
Mask should be inverted before AND -> Option AQuick Check:
Clear bit = AND with inverted mask [OK]
- Using mask without inversion to clear bits
- Using OR instead of AND to clear bits
- Confusing bit positions
flags is set (1). Which code snippet correctly does this and prints "Set" if true, otherwise "Not set"?Solution
Step 1: Understand checking a bit
To check if a bit is set, AND the number with a mask having 1 at that bit. If result is not zero, bit is set.Step 2: Analyze options
if ((flags & (1 << 4)) != 0) printf("Set"); else printf("Not set"); uses (flags & (1 << 4)) != 0 which correctly checks the 4th bit.
if ((flags | (1 << 4)) == 0) printf("Set"); else printf("Not set"); uses OR and compares to zero, which is incorrect.
if ((flags ^ (1 << 4)) == 1) printf("Set"); else printf("Not set"); uses XOR and compares to 1, which is incorrect.
if ((flags & (1 << 3)) != 0) printf("Set"); else printf("Not set"); checks bit 3 instead of 4, so wrong bit.Final Answer:
if ((flags & (1 << 4)) != 0) printf("Set"); else printf("Not set"); -> Option CQuick Check:
Check bit = AND with mask != 0 [OK]
- Using OR or XOR to check bits
- Checking wrong bit position
- Comparing AND result incorrectly
Ready to prove it?
Pass the test and this pattern moves unknown
