CMD Guide
HomeDSABit Manipulation

medium Bitwise AND of Numbers Range

Bitwise AND of Numbers Range

Problem. Given two integers left and right with 0 ≤ left ≤ right, return the bitwise AND of every integer in the inclusive range [left, right]: left & (left+1) & … & right.

Naive baseline. Loop i from left to right, AND them all. Correct, but the range can be enormous — with right up to 2⁷¹ - 1 the loop can run billions of times and time out. We need a way to get the answer without visiting every number. The bit structure hands it to us.

The insight — the answer is the common binary prefix

Claim: AND(left..right) equals the longest common leading bit prefix of left and right, with every lower bit set to 0.

Proof of why differing bits vanish. AND turns a bit off if any number in the range has a 0 there. Let i be the highest bit position where left and right differ (if none, left == right and the answer is just left). Every bit above i is identical in left and right — the common prefix — so it is identical for every number in between too, and AND preserves it. For bit i and everything below it: since left < right and they agree above i, left has a 0 at bit i and right has a 1. Consider the number P1 = the common prefix, a 1 at bit i, and 0s below. Then left < P1 ≤ right, so P1 is in the range, and its predecessor P1 - 1 = prefix, 0 at bit i, and all 1s below — is also in the range (it is ≥ left). Now take any bit j ≤ i: exactly one of P1 and P1 - 1 has a 0 there. So every bit from i down is zeroed by the AND. What survives is precisely the common prefix followed by zeros. □

Approach 1 — strip differing suffix by shifting both together

To find the common prefix, shift left and right right in lockstep until they are equal — that throws away exactly the differing low bits. Count the shifts, then shift the common value back left the same amount to put the zeros back where the low bits were.

shift = 0
while (left != right) { left >>= 1; right >>= 1; shift++; }
return left << shift;   // common prefix, low bits restored as 0

Traced example — AND of [5, 7]

5 = 101, 6 = 110, 7 = 111. The true answer is 101 & 110 & 111 = 100 = 4. Watch Approach 1 recover it without touching 6:

stepleftrightequal?shift
0101 (5)111 (7)no0
1010 (2)011 (3)no1
2001 (1)001 (1)yes → stop2

Common prefix is 1, shifted back by 2: 1 << 2 = 100 = 4. Correct, and we never enumerated the range. The differing low 2 bits were shifted out and returned as zeros — exactly what the proof predicted.

Approach 2 — Kernighan: strip right's lowest set bit until it drops below left

right & (right - 1) clears the lowest set bit of right (subtracting 1 flips the lowest 1 to 0 and the bits below it to 1; ANDing with the original keeps only the higher bits). Repeatedly clearing right's low set bits while right > left walks right down to the common prefix. When right ≤ left, the low differing bits are gone and right holds the answer.

while (left < right) { right &= right - 1; }
return right;

On [5, 7]: right = 7 & 6 = 6 (still > 5) → right = 6 & 5 = 4 (now < 5, stop) → return 4. Same answer, verified by execution.

Java: common-prefix by shifting

public class Solution {
    public int rangeBitwiseAnd(int left, int right) {
        int shift = 0;
        while (left != right) {   // inputs are non-negative, so >> is safe
            left  >>= 1;
            right >>= 1;
            shift++;
        }
        return left << shift;
    }

    // Alternative: Kernighan shrink
    public int rangeBitwiseAndK(int left, int right) {
        while (left < right) right &= right - 1;
        return right;
    }

    public static void main(String[] args) {
        Solution s = new Solution();
        System.out.println(s.rangeBitwiseAnd(5, 7));    // 4
        System.out.println(s.rangeBitwiseAnd(0, 0));    // 0
        System.out.println(s.rangeBitwiseAndK(12, 15)); // 12
    }
}

Go: common-prefix by shifting

package main

import "fmt"

func rangeBitwiseAnd(left, right int) int {
    shift := 0
    for left != right {
        left >>= 1
        right >>= 1
        shift++
    }
    return left << shift
}

func rangeBitwiseAndK(left, right int) int { // Kernighan shrink
    for left < right {
        right &= right - 1
    }
    return right
}

func main() {
    fmt.Println(rangeBitwiseAnd(5, 7))    // 4
    fmt.Println(rangeBitwiseAnd(0, 0))    // 0
    fmt.Println(rangeBitwiseAndK(12, 15)) // 12
}

Complexity

Judgment layer — when the bit trick is essential, and when the naive loop is fine

Traps & edge cases


Authored for this guide from first principles (LeetCode 201). The common-prefix proof is derived above; [5,7]→4, [12,15]→12, [0,0]→0, and [10,10]→10 — along with the raw checks 5&6&7=4 and 12&13&14&15=12 — were confirmed by running both the shift and Kernighan variants in Java 8 and Go 1.25.

🧩 Pattern · Bit Manipulation

Recognize it: Presence / pairing / parity with XOR and masks → think in bits.

→ more Bit Manipulation problems, grouped
🤖 Don't fully get this? Learn it with Claude

Stuck on Bitwise AND of Numbers Range? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🪜 Hint ladder (no spoilers)

Progressively stronger hints — you still solve it.

I'm working on the problem **Bitwise AND of Numbers Range** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🎨 Explain the approach visually

See the technique, not just code.

Explain the optimal approach to **Bitwise AND of Numbers Range** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔍 Review my solution

Catch bugs, edge cases, sub-optimality.

I'll paste my solution to **Bitwise AND of Numbers Range**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔁 Drill the pattern

Lock in recognition with look-alikes.

Give me 2 problems that use the SAME underlying pattern as **Bitwise AND of Numbers Range**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes