Bit Manipulation · 3 of 10
Count number of bits to be flipped to convert A to B
Count how many light switches you must flip so one row of switches looks exactly like another.
- Simple way
- time O(log max(A, B))
room O(1) - Clever way
- time O(k)
room O(1)
The problem, simply
You get two whole numbers, A and B. Write both in bits. A flip changes one bit, from 0 to 1 or from 1 to 0.
How many flips does it take to turn A into B? That is the number of places where their bits do not match.
A story to remember it
Picture it
A = 10 and B = 20. They disagree at bits 1, 2, 3 and 4, so 4 flips are needed. They agree only at bit 0.
- checking
Examples
A normal case
- In
A = 10, B = 20- Out
4
01010 against 10100. Only the rightmost bit matches. The other four differ.
Different lengths
- In
A = 7, B = 10- Out
3
0111 against 1010. They differ at bits 0, 2 and 3. Pad the shorter one with 0s on the left before you compare.
Same number
- In
A = 5, B = 5- Out
0
Nothing differs, so nothing needs a flip.
A negative number
- In
A = -1, B = 0- Out
32
-1 is 32 ones in a Java int, and 0 is 32 zeros. Every bit differs. Code that loops while (x > 0) wrongly says 0 here.
Way 1: the simple way
Compare the two numbers one bit at a time, from the right.
- Look at the last bit of each:
A & 1andB & 1. - If they differ, add 1 to the count.
- Slide both numbers one place right with
>>>and repeat until both are 0.
class Solution {
public static int countFlips(int a, int b) {
int count = 0;
while (a != 0 || b != 0) {
if ((a & 1) != (b & 1)) {
count++; // this pair of bits does not match
}
a >>>= 1; // >>> pulls in 0s, so negatives finish too
b >>>= 1;
}
return count;
}
}How long it takes: one round per bit of the bigger number, O(log max(A, B)), at most 32 rounds. Extra room: O(1).
Way 2: the clever way
Two tricks, one after the other.
- XOR finds the differences.
A ^ Bhas a 1 exactly whereAandBdisagree. So the answer is the number of 1s inA ^ B. - To count 1s fast, use
x & (x - 1). Taking 1 away fromxturns its lowest 1 into a 0 and the 0s under it into 1s. ANDing withxwipes out that lowest 1 and nothing else. - Repeat until
xis 0. The number of rounds is the number of 1s.
XOR, then wipe out one 1 at a time
01 / 07
A = 10 is 01010 and B = 20 is 10100. We want to count the spots where they do not match.
- looking now
- checking
- answer
- rejected
- just added
class Solution {
public static int countFlips(int a, int b) {
int x = a ^ b; // 1 wherever a and b disagree
int count = 0;
while (x != 0) { // != 0, not > 0, so negatives work
x &= x - 1; // wipe out the lowest 1
count++;
}
return count;
}
}How long it takes: one round per differing bit. If k bits differ, that is O(k) rounds, never more than 32. Extra room: O(1).
Watch out for
- Comparing the numbers in decimal digits. Flips are about bits, so 10 and 20 need 4 flips, not 1.
- Java has
Integer.bitCount(a ^ b)built in. Mention it, but be ready to write the loop yourself. - Equal numbers give
A ^ B = 0, so the loop never runs and the answer is 0.
What interviewers ask next
- What is this number called? The Hamming distance between
AandB. - Sum of Hamming distances over every pair in an array? Do it per bit: if
cnumbers have bition andn - chave it off, that bit addsc * (n - c). TotalO(32 n), notO(n^2). - Why does
x & (x - 1)drop the lowest 1? Everything above the lowest 1 is the same inxandx - 1. The lowest 1 and everything below it are opposite, so AND gives 0 there. - Can you count 1s in constant steps? Yes, with a 256 entry table looked up once per byte, or with the add-in-pairs trick that
Integer.bitCountuses.
Remember this
Grown-up words: the see-through sheet is XOR, the glowing spots are set bits, the count is the Hamming distance, and the sticker trick is Brian Kernighan's way of counting set bits.