CMD Guide
HomeDSABit Manipulation

easy Counting Bits

Counting Bits

Given an integer n, return an array ans of length n + 1 where ans[i] is the number of set bits in i, for every i from 0 to n. For n = 5 the answer is [0, 1, 1, 2, 1, 2].

The single-number version (Number of 1 Bits) is a warm-up. What makes this problem worth studying is that it is secretly a dynamic-programming problem on bits: the answer for i is one array lookup away from an answer you already computed. Spotting that recurrence is the whole point.

The naive baseline — popcount every number independently

Run a Hamming-weight count (e.g. Kernighan's x & (x-1) loop) once per value:

for (int i = 0; i <= n; i++) ans[i] = popcount(i);

Each popcount costs up to O(32) (or O(log i)) bit steps, so the total is O(n · 32). Correct, but it recomputes from scratch every time and throws away work it just did on smaller numbers.

The bit insight — reuse a smaller answer (two recurrences)

Recurrence A — drop the last bit: ans[i] = ans[i >> 1] + (i & 1). Right-shifting i by one deletes its lowest bit and keeps every other bit, just slid down one position. Shifting does not create or destroy the remaining 1s, so i >> 1 has exactly the set bits of i except the one we shifted out. That discarded bit was worth i & 1 (1 if i was odd, 0 if even). Hence popcount(i) = popcount(i >> 1) + (i & 1). And since i >> 1 < i for i > 0, that subproblem is already solved — a textbook overlapping subproblem.

Recurrence B — clear the last set bit: ans[i] = ans[i & (i - 1)] + 1. We proved on the previous page that i & (i - 1) removes exactly one set bit. So i & (i-1) has one fewer 1 than i, and it is strictly smaller than i, so it too is already computed. Add 1 for the bit we removed.

Either recurrence turns each entry into one comparison and one array readO(1) per number, O(n) overall. This is dynamic programming: define the state (ans[i] = popcount of i), find a transition to a smaller solved state, fill bottom-up.

Traced example — n = 5, using ans[i] = ans[i>>1] + (i&1)

ibinaryi >> 1ans[i>>1]i & 1ans[i]
00000 (base case)
1001000 = 0010 + 1 = 1
2010001 = 1101 + 0 = 1
3011001 = 1111 + 1 = 2
4100010 = 2101 + 0 = 1
5101010 = 2111 + 1 = 2

Result: [0, 1, 1, 2, 1, 2]. Cross-check by hand: 3 = 11 (2 bits), 4 = 100 (1 bit), 5 = 101 (2 bits). Every entry was one lookup plus a parity bit.

Java: DP on bits

public class Solution {
    // ans[i] = ans[i >> 1] + (i & 1)
    public int[] countBits(int n) {
        int[] ans = new int[n + 1];   // ans[0] = 0 by default
        for (int i = 1; i <= n; i++) {
            ans[i] = ans[i >> 1] + (i & 1);
        }
        return ans;
    }

    public static void main(String[] args) {
        System.out.println(java.util.Arrays.toString(new Solution().countBits(5)));
        // [0, 1, 1, 2, 1, 2]
        System.out.println(java.util.Arrays.toString(new Solution().countBits(2)));
        // [0, 1, 1]
    }
}

Go: DP on bits

package main

import "fmt"

// ans[i] = ans[i>>1] + (i & 1)
func countBits(n int) []int {
	ans := make([]int, n+1) // ans[0] == 0 (zero value)
	for i := 1; i <= n; i++ {
		ans[i] = ans[i>>1] + (i & 1)
	}
	return ans
}

func main() {
	fmt.Println(countBits(5)) // [0 1 1 2 1 2]
	fmt.Println(countBits(2)) // [0 1 1]
}

Complexity

Judgment layer — when the DP earns its place

Edge cases & traps

Takeaways

🧩 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 Counting Bits? 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 **Counting Bits** (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 **Counting Bits** 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 **Counting Bits**. 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 **Counting Bits**. 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