Topics › Bit Manipulation › Interview Problems
Minimum Bit Flips to Convert Number
LeetCode ↗ Java source ↗ Edit this article ↗
Jump to code:
Problem
A bit flip changes a single bit of a number from 0 to 1 or from 1 to 0. You are given two integers start and goal. Return the minimum number of bit flips needed to turn start into goal. Leading zeros count as bits, so turning 3 = 011 into 4 = 100 takes three flips.
Constraints: 0 ≤ start, goal ≤ 10^9. The solutions below also work for negative inputs, treating them as 32-bit patterns.
Example 1
start = 10, goal = 7
answer = 3 // 1010 -> 0111: bits 0, 2 and 3 differ
Example 2
start = 3, goal = 4
answer = 3 // 011 -> 100: every one of the three low bits differs
Example 3
start = 5, goal = 5
answer = 0 // nothing to flip
Why the answer is the number of differing bits
Each flip changes exactly one bit position, and flipping a position twice is a waste. A position where start and goal already agree needs no flip; a position where they disagree needs exactly one. Flips at different positions do not interfere with each other. So the minimum is precisely the number of positions where the two numbers differ: the Hamming distance between start and goal. Every approach below counts those positions; they differ only in how.
Approach 1: Brute force, compare each position
Intuition. Walk through all 32 bit positions, extract bit i of each number with (x >> i) & 1, and count the positions where the two bits differ. There is nothing to prove: it is the definition.
Algorithm.
flips = 0.- For
ifrom0to31: if((start >> i) & 1) != ((goal >> i) & 1), incrementflips. - Return
flips.
static int bruteForce(int start, int goal) {
int flips = 0;
for (int i = 0; i < 32; i++) {
if (((start >> i) & 1) != ((goal >> i) & 1)) flips++;
}
return flips;
}
Complexity. Time O(32), which is constant but always the full 32 iterations. Space O(1).
Approach 2: Better, XOR then count ones
Intuition. XOR produces a 1 exactly where its two inputs differ and a 0 where they agree. So start ^ goal is a number whose set bits mark precisely the positions that must be flipped, and the problem collapses to counting set bits. Count them by reading the lowest bit and shifting right with >>> until nothing is left; the unsigned shift guarantees termination even if the XOR is negative.
Algorithm.
diff = start ^ goal,flips = 0.- While
diff != 0:flips += diff & 1,diff >>>= 1. - Return
flips.
static int better(int start, int goal) {
int diff = start ^ goal;
int flips = 0;
while (diff != 0) {
flips += diff & 1;
diff >>>= 1;
}
return flips;
}
Complexity. Time O(position of the highest differing bit): the loop stops as soon as diff runs out of bits, so for 10 and 7 it runs 4 times, not 32. Space O(1).
Approach 3: Optimal, XOR then Brian Kernighan
Intuition. n & (n - 1) clears the lowest set bit of n and nothing else, because n - 1 flips that bit and the zeros below it while leaving the higher bits alone. Applying it repeatedly to diff removes one differing position per round, so the number of rounds is the number of flips. The loop now runs once per flip rather than once per bit, which is the best possible for a counting loop: it does exactly as much work as the answer is large.
Algorithm.
diff = start ^ goal,flips = 0.- While
diff != 0:diff &= diff - 1,flips++. - Return
flips.
static int optimal(int start, int goal) {
int diff = start ^ goal;
int flips = 0;
while (diff != 0) {
diff &= diff - 1;
flips++;
}
return flips;
}
Dry run on start = 10 = 1010, goal = 7 = 0111: diff = 1010 ^ 0111 = 1101.
| round | diff | diff - 1 | diff & (diff - 1) | flips |
|---|---|---|---|---|
| 1 | 1101 | 1100 | 1100 | 1 |
| 2 | 1100 | 1011 | 1000 | 2 |
| 3 | 1000 | 0111 | 0000 | 3 |
Complexity. Time O(k) where k is the answer, at most 32. Space O(1).
In Java the whole thing is also a one-liner using the library popcount, which the JIT compiles to a single hardware instruction:
static int optimalBuiltin(int start, int goal) {
return Integer.bitCount(start ^ goal);
}
Use this in production and the Kernighan loop in interviews, where the point is to show that you know why n & (n - 1) works.
Edge cases and pitfalls
- Equal numbers.
start ^ goalis0and every method returns0immediately. - Zero.
start = 0means the answer is simply the popcount ofgoal;goal = 0is the popcount ofstart.10^9has 13 set bits, so(1000000000, 0)gives13. - Different bit lengths.
3and4have the same number of digits but1and1024do not; the missing leading zeros of the shorter number are real bits in the 32-bit word and are compared like any other. The answer for(0, 1 << 30)is1. - Negative inputs. Not in the constraints, but harmless:
(-1, 0)gives32,(Integer.MIN_VALUE, Integer.MAX_VALUE)gives32, and(-1, Integer.MAX_VALUE)gives1because only the sign bit differs. Approach 2 needs>>>for this; with>>the loop on a negativediffwould never terminate. - Symmetry. XOR is commutative, so
flips(start, goal) == flips(goal, start); the tests check this on a grid of pairs. - Counting the wrong thing. The answer is the popcount of the XOR, not the difference of the popcounts:
3 = 011has popcount2and4 = 100has popcount1, a difference of1, yet the answer is3.
Related problems
- Count the Number of Set Bits is the counting step on its own, with the lookup-table variant.
- Introduction to Bits and Tricks explains why XOR marks differences and why
n & (n - 1)drops one bit. - Single Number - I is the other classic use of XOR cancelling matching bits.
- Set/Unset the rightmost unset bit studies the
n & (n - 1)operation in isolation.