201. Bitwise AND of Numbers Range - Explanation

Problem Link

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: 0

Example 2:

Input: left = 10, right = 12

Output: 8

Constraints:

  • 0 <= left <= right <= ((2^31)-1)


Topics

Company Tags

Please upgrade to NeetCode Pro to view company tags.



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

  1. Initialize the result with the left boundary value.
  2. Iterate from left + 1 to right (inclusive).
  3. For each number, perform a bitwise AND with the current result.
  4. Return the final result.
class Solution:
    def rangeBitwiseAnd(self, left: int, right: int) -> int:
        res = left
        for i in range(left + 1, right + 1):
            res &= i
        return res

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(1)O(1)

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

  1. Initialize result to 0.
  2. For each bit position i from 0 to 31:
    • Check if bit i is set in left. If not, skip (result bit stays 0).
    • Calculate the remainder of left when divided by 2^(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 bit i in the result.
  3. Return the result.
class Solution:
    def rangeBitwiseAnd(self, left: int, right: int) -> int:
        res = 0
        for i in range(32):
            bit = (left >> i) & 1
            if not bit:
                continue

            remain = left % (1 << (i + 1))
            diff = (1 << (i + 1)) - remain
            if right - left < diff:
                res |= (1 << i)

        return res

Time & Space Complexity

  • Time complexity: O(1)O(1) since we iterate 3232 times.
  • Space complexity: O(1)O(1)

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

  1. Initialize a counter i to 0.
  2. While left and right are not equal:
    • Right-shift both left and right by 1.
    • Increment i.
  3. Left-shift the common value (left or right) back by i positions.
  4. Return the result.
class Solution:
    def rangeBitwiseAnd(self, left: int, right: int) -> int:
        i = 0
        while left != right:
            left >>= 1
            right >>= 1
            i += 1
        return left << i

Time & Space Complexity

  • Time complexity: O(1)O(1)
  • Space complexity: O(1)O(1)

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

  1. While left is less than right:
    • Apply the operation right = right AND (right - 1) to clear the rightmost set bit of right.
  2. Return right (which now equals the common prefix with trailing zeros).
class Solution:
    def rangeBitwiseAnd(self, left: int, right: int) -> int:
        while left < right:
            right &= right - 1
        return right

Time & Space Complexity

  • Time complexity: O(1)O(1)
  • Space complexity: O(1)O(1)

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 bits

Integer 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;