By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
"This problem appears in 1 out of every 3 onsite interviews—mastering it proves you can optimize bitwise operations, recognize dynamic programming patterns, and write clean, efficient code under pressure."
Before tackling this problem, ensure you understand: 1. Bitwise operations (&, >>, <<, ~) – How to manipulate individual bits. 2. Dynamic Programming (DP) – Memoization and optimal substructure. 3. Brian Kernighan’s Algorithm – Efficiently counting set bits in an integer.
&
>>
<<
~
n &= (n - 1)
dp[i] = dp[i >> 1] + (i & 1)
i & 1
i
dp[i] = dp[i & (i - 1)] + 1
Repeatable mental checklist for every "Counting Bits" problem:
n
result[i]
0 ≤ i ≤ n
Example: n = 5 → [0, 1, 1, 2, 1, 2].
n = 5
[0, 1, 1, 2, 1, 2]
Brute-Force Check (Baseline)
0
while i: count += i & 1; i >>= 1
Time: O(n log n) (inefficient for large n).
O(n log n)
Optimize with Brian Kernighan’s Algorithm
i &= (i - 1)
Time per number: O(k) where k = number of set bits (better than O(log n)).
O(k)
k
O(log n)
Apply Dynamic Programming (DP)
i >> 1
Time: O(n) (optimal).
O(n)
Edge Cases & Validation
n = 0
[0]
n = 1
[0, 1]
Large n (e.g., 10^5) – Ensure DP approach scales.
10^5
Write Clean Code
dp[0] = 0
Iterate from 1 to n, applying the DP formula.
1
Verify with Examples
n = 2
[0, 1, 1]
Problem: Count set bits for all numbers from 0 to n.
Solution:
def countBits(n: int) -> list[int]: dp = [0] (n + 1) for i in range(1, n + 1): dp[i] = dp[i >> 1] + (i & 1) return dp
Time: O(n) | Space: O(n)
Why this works: - i >> 1 is equivalent to i // 2 (right shift by 1). - i & 1 checks if i is odd (LSB is 1). - DP reuses previous computations, avoiding redundant work.
i // 2
Problem: Count set bits for a single number n (not an array).
def countSetBits(n: int) -> int: count = 0 while n: n &= (n - 1) # Clears the rightmost set bit count += 1 return count
Time: O(k) where k = number of set bits | Space: O(1)
O(1)
Why this works: - n &= (n - 1) flips the rightmost set bit to 0. - Each iteration removes one set bit, so the loop runs k times.
Problem: Given low and high, return the total number of set bits in all numbers from low to high.
low
high
def rangeBitCount(low: int, high: int) -> int: def countBits(n: int) -> list[int]: dp = [0] (n + 1) for i in range(1, n + 1): dp[i] = dp[i >> 1] + (i & 1) return dp dp = countBits(high) return sum(dp[low:high + 1])
Time: O(high) | Space: O(high)
O(high)
Optimization (Advanced): - Use digit DP for O(log high) time (beyond FAANG scope, but good to know).
O(log high)
Why this works: - Precompute dp for all numbers up to high. - Sum the range [low, high] in O(1) per query.
dp
[low, high]
dp = [0] (n + 1)
(i & 1)
bin(i).count("1")
i & (i - 1)
"Alright, let’s lock this in. For ‘Counting Bits’ problems, here’s your 30-second cheat sheet:
Now go crush that interview. You’ve got this!
This guide is 100% interview-ready—every line is actionable under pressure. Good luck! ?
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.