Solving tips
- Key insight: a bit survives the AND only if it is 1 in every number of the range; low bits churn through 0 and 1 and die, so the answer is exactly the common binary PREFIX of left and right.
- Method 1: right-shift both left and right until equal (counting shifts), then shift the shared value back left, left << shift.
- Method 2 (Brian Kernighan): repeatedly clear right's lowest set bit with right &= right-1 while left < right; the result is the common prefix.
- Target O(log n) time, O(1) space, never iterate the range (it can hold billions); left=0 naturally yields 0.
Problem
Given two integers left and right with left <= right, return the bitwise AND of every integer in the inclusive range [left, right] β that is, left & (left + 1) & ... & right.
Examples
left = 5, right = 7 β 4 β 101 & 110 & 111 = 100 = 4.
left = 0, right = 0 β 0 β a single number ANDed with nothing else is itself.
left = 1, right = 2147483647 β 0 β such a huge range clears every bit.
Constraints
0 <= left <= right <= 2^31 - 1
The range can hold billions of numbers, so you cannot actually loop over it β the AND must be found structurally, in about O(log n) steps.
Think about it first
Hint 1
A bit is `1` in the answer only if it is `1` in *every* number of the range. The moment any number in the range has a `0` there, that bit is dead. Which bits can possibly stay `1` across a contiguous run of integers?
Hint 2
Low bits flip constantly as you count upward, so they get zeroed. Only the high bits that `left` and `right` already share β their common binary prefix β can survive. The answer is that prefix, padded with zeros.
Hint 3
Right-shift both `left` and `right` until they become equal (that's the common prefix), counting the shifts, then shift the prefix back left. Alternatively, keep clearing the lowest set bit of `right` (`right &= right - 1`) until `right <= left`.
TL;DR
The AND over [left, right] is the common binary prefix of left and right β find it in O(log n) time, O(1) space; the literal loop is hopeless.
Approach 1 β Brute force: AND the whole range
The naive intuition: start from left and AND in every successive number up to right.
class Solution:
def rangeBitwiseAnd(self, left: int, right: int) -> int:
result = left
for num in range(left + 1, right + 1):
result &= num
if result == 0: # can only shrink; 0 is absorbing
break
return result
Complexity: O(right - left) time, O(1) space.
Why the constraints kill it: with left = 1, right = 2^31 - 1 the loop wants ~2 billion iterations. Even with the early break, ranges that stay nonzero (e.g. [2^30, 2^30 + 10^9]) run far past any time limit.
Approach 2 β Common prefix by shifting
The insight: a bit survives the AND only if it is 1 in every number of the range. Across a contiguous run of integers, every bit below the highest position where left and right differ takes on both values 0 and 1 somewhere in the range (thatβs just counting), so each such bit is ANDed to 0. Only the high bits that left and right already agree on β their common binary prefix β can remain 1. Find that prefix by right-shifting both numbers until they coincide, tracking how far you shifted, then shift the shared value back into place and let the vacated low bits be 0.
class Solution:
def rangeBitwiseAnd(self, left: int, right: int) -> int:
shift = 0
while left < right:
left >>= 1
right >>= 1
shift += 1
return left << shift # common prefix, zero-padded
Walkthrough on left = 5, right = 7:
| step | left | right | shift |
|---|
| 0 | 101 (5) | 111 (7) | 0 |
| 1 | 10 (2) | 11 (3) | 1 |
| 2 | 1 (1) | 1 (1) | 2 |
left == right == 1, loop stops. Return 1 << 2 = 100 = 4. β The shared prefix is 1, and the two low bits (which varied across 5, 6, 7) are zeroed.
Complexity: O(log n) time β at most ~31 shifts β O(1) space.
Approach 3 β Brian Kernighan: clear low bits of right
The insight: instead of shrinking both numbers, repeatedly strip the lowest set bit from right with right & (right - 1). Each stripped bit is a low bit that varies within the range and therefore cannot appear in the answer. Keep going until right drops to left or below; at that point every bit that differed has been cleared and right holds exactly the common prefix. (n & (n - 1) clears the lowest set bit β the standard Kernighan idiom.)
class Solution:
def rangeBitwiseAnd(self, left: int, right: int) -> int:
while left < right:
right &= right - 1 # clear right's lowest set bit
return right
Walkthrough on left = 5, right = 7:
| step | right (binary) | right & (right - 1) | left < right? |
|---|
| 1 | 111 (7) | 110 (6) | 5 < 6, continue |
| 2 | 110 (6) | 100 (4) | 5 < 4? no, stop |
Return right = 4. β
Complexity: O(number of set bits cleared) β€ O(log n) time, O(1) space.
Common pitfalls
- Trying to loop the range: the range size is up to 2^31; any per-number loop times out. This must be structural.
left <= right vs left < right in the loop: use strict <; when theyβre already equal the answer is that value with no shifting.
- Forgetting to shift back: in Approach 2 the count of shifts must be reapplied (
left << shift), or you return the prefix at the wrong magnitude.
left == 0: if left is 0, the answer is 0 (the range includes 0, which ANDs everything away) β both approaches handle it naturally, but itβs the classic edge case to check.
Pattern takeaway
Bitwise AND over a contiguous integer range collapses to the numbersβ common high prefix: low bits churn through both values and die, only shared leading bits live. Recognize βAND over a rangeβ as a common-prefix problem β solvable by shifting to the shared prefix or by Kernighan-clearing the low bits β never by iterating the range.