A bit flip of a number x
is choosing a bit in the binary representation of x
and flipping it from either 0
to 1
or 1
to 0
. For example, for x = 7
, the binary representation is 111
and we may choose any bit (including any leading zeros not shown) and flip it. We can flip the first bit from the right to get 110
, flip the second bit from the right to get 101
, flip the fifth bit from the right (a leading zero) to get 10111
, etc.
Given two integers start
and goal
, return the minimum number of bit flips to convert start
to goal
.
For example:
start = 10
and goal = 7
, the output should be 3
. The binary representation of 10 and 7 are 1010 and 0111 respectively. We can convert 10 to 7 in 3 steps:
1010
-> 1011
.1011
-> 1111
.1111
-> 0111
.start = 3
and goal = 4
, the output should be 3
. The binary representation of 3 and 4 are 011 and 100 respectively. We can convert 3 to 4 in 3 steps:
011
-> 010
.010
-> 000
.000
-> 100
.Write a function to solve this problem efficiently.
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The goal is to figure out how many changes we need to make to one number to turn it into another. The brute force method directly compares each matching part of the numbers and counts the differences.
Here's how the algorithm would work step-by-step:
def min_bit_flips_brute_force(start_number, goal_number):
bit_flip_count = 0
# Convert integers to binary strings
start_number_binary = bin(start_number)[2:]
goal_number_binary = bin(goal_number)[2:]
# Find the length of the longer binary string
max_length = max(len(start_number_binary), len(goal_number_binary))
# Pad the shorter string with leading zeros to match lengths. Important for comparison.
start_number_binary = start_number_binary.zfill(max_length)
goal_number_binary = goal_number_binary.zfill(max_length)
for bit_index in range(max_length):
# Compare bits at each index and increment the flip count if they differ.
if start_number_binary[bit_index] != goal_number_binary[bit_index]:
bit_flip_count += 1
return bit_flip_count
The goal is to find the minimum number of bit flips needed to transform one number into another. Instead of comparing all bits individually, a key insight is to isolate the bits that are different between the two numbers using an exclusive OR operation.
Here's how the algorithm would work step-by-step:
def min_bit_flips(start_number, goal_number):
# XOR identifies differing bits.
xor_result = start_number ^ goal_number
bit_flips_needed = 0
# Count the number of set bits.
while xor_result > 0:
# Check the rightmost bit.
if (xor_result & 1) == 1:
bit_flips_needed += 1
# Right-shift to check the next bit.
xor_result >>= 1
return bit_flips_needed
Case | How to Handle |
---|---|
Both start and goal are zero | Return 0, as no bits need to be flipped. |
Start and goal are the same number | Return 0, as no bits need to be flipped. |
Start is zero, goal is a large positive number | The number of flips will equal the number of set bits in the goal, and the solution should efficiently count them. |
Start is a large positive number, goal is zero | The number of flips will equal the number of set bits in the start, and the solution should efficiently count them. |
Integer overflow if intermediate calculations are not handled carefully | Bitwise XOR operation is used, which inherently avoids overflow concerns. |
Maximum integer value for start or goal | The bitwise XOR and bit counting will work correctly with maximum integer values. |
Negative integer inputs (if applicable depending on language and problem constraints) | If negative numbers are allowed, use unsigned right shift (>>> in Java, etc.) to ensure logical shifts, and handle the sign bit correctly or ensure input is within acceptable range (non-negative). |
Inputs where start and goal only differ by one or two bits. | The bit counting algorithm should correctly handle small differences between the numbers. |