201. Bitwise AND of Numbers Range - Explanation
Description
You are given two integers left and right that represent the range [left, right], return the bitwise AND of all numbers in this range, inclusive.
Example 1:
Input: left = 1, right = 5
Output: 0Example 2:
Input: left = 10, right = 12
Output: 8Constraints:
0 <= left <= right <= ((2^31)-1)
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Bit Manipulation - Understanding bitwise AND, OR, and shift operations
- Binary Number Representation - Recognizing how numbers are represented in binary and how bits change across a range
- Common Bit Tricks - Techniques like clearing the rightmost set bit using n & (n-1)
1. Brute Force
Intuition
The most straightforward approach is to AND all numbers in the range together. Starting with the left boundary, we iterate through each number up to the right boundary, accumulating the AND result. While simple, this is inefficient for large ranges.
Algorithm
- Initialize the result with the
leftboundary value. - Iterate from
left + 1toright(inclusive). - For each number, perform a bitwise AND with the current result.
- Return the final result.
Time & Space Complexity
- Time complexity:
- Space complexity:
2. Bit Manipulation - I
Intuition
For any bit position in the result to be 1, that bit must be 1 in all numbers from left to right. If a bit is 1 in left, we need to check if it will flip to 0 at some point in the range. A bit at position i flips when we reach the next multiple of 2^(i+1). So we calculate how far left is from that flip point and check if right is still before it.
Algorithm
- Initialize result to
0. - For each bit position
ifrom0to31:- Check if bit
iis set inleft. If not, skip (result bit stays0). - Calculate the remainder of
leftwhen divided by2^(i+1). - Calculate the distance to the next flip:
2^(i+1)minus the remainder. - If
(right - left)is less than this distance, the bit survives in all numbers, so set bitiin the result.
- Check if bit
- Return the result.
Time & Space Complexity
- Time complexity: since we iterate times.
- Space complexity:
3. Bit Manipulation - II
Intuition
The result is the common prefix of the binary representations of left and right. When left and right differ, the differing bits and all bits to the right will become 0 in the AND result (since there will be at least one 0 in each of those positions across the range). We find this common prefix by right-shifting both numbers until they are equal.
Algorithm
- Initialize a counter
ito0. - While
leftandrightare not equal:- Right-shift both
leftandrightby1. - Increment
i.
- Right-shift both
- Left-shift the common value (
leftorright) back byipositions. - Return the result.
Time & Space Complexity
- Time complexity:
- Space complexity:
4. Bit Manipulation - III
Intuition
Instead of shifting both numbers, we can repeatedly clear the rightmost set bit of right until right becomes less than or equal to left. The operation (n & (n-1)) clears the lowest set bit of n. This works because any bit position where right has a 1 but needs to flip within the range will be cleared, leaving only the common prefix.
Algorithm
- While
leftis less thanright:- Apply the operation
right = right AND (right - 1)to clear the rightmost set bit ofright.
- Apply the operation
- Return
right(which now equals the common prefix with trailing zeros).
Time & Space Complexity
- Time complexity:
- Space complexity:
Common Pitfalls
Iterating Through All Numbers in the Range
The brute force approach of ANDing every number from left to right will time out for large ranges. For example, when left = 1 and right = 2^31 - 1, this requires billions of operations.
Misunderstanding the Common Prefix Property
The result is the common binary prefix of left and right with trailing zeros. A common mistake is trying to AND only left and right directly, missing that intermediate values determine which bits survive.
# Wrong: only checking left and right
return left & right # Misses intermediate values that clear bitsInteger Overflow in Bit Calculations
When calculating (1 << (i + 1)) for bit position 31, the result exceeds 32-bit signed integer range in some languages. Use unsigned types or 64-bit integers to avoid overflow.
// Wrong in C++: signed overflow at i=31
int diff = (1 << (i + 1)) - remain; // Overflow when i=31
// Correct: use unsigned
uint diff = (1ul << (i + 1)) - remain;
Sign in to join the discussion