Browse curriculum

Counting Bits

Given an integer n, return an array of the number of 1's for each number from 0 to n.

Examples

Input:n = 2
Output:[0,1,1]
Explain:

0 is 0, 1 is 1, 2 is 10 — so the counts are 0, 1 and 1.

Input:n = 5
Output:[0,1,1,2,1,2]
Explain:

5 is 101; shifted right it is 10, which is 2 with one bit, and the dropped digit is 1 — so dp[5] = 2.

Problem Understanding

We need to return an array ans of size n + 1 such that for each i, ans[i] counts the 1 bits when i is written in binary.

Example: n = 2

  • 0 -> 0 (0)
  • 1 -> 1 (1)
  • 2 -> 10 (1)
  • Output: [0, 1, 1]

Algorithm Strategy

Counting the bits of one number costs O(log n), so doing it for all of them costs O(n log n). Dynamic programming makes it O(n).

The insight: i >> 1 is i with its last binary digit thrown away. It therefore has every bit of i except that one, and i & 1 is exactly the digit that was thrown away.

Recurrence: dp[i] = dp[i >> 1] + (i & 1)

Because i >> 1 is always smaller than i, the value it needs has already been written — so one forward pass is enough.

Interactive Visualization

Each column is one number and holds its count of 1 bits. Watch the outlined cell: it is always i >> 1, the same number with its last binary digit dropped — and the panel beside the figure lines the two up so you can see which digit went missing.

Try Past 8: every power of two drops the count straight back to 1.

Dry Run

n = 5

i Binary i >> 1 dp[i >> 1] i & 1 Result dp[i]
0 000 0 0 0 0
1 001 0 0 1 1
2 010 1 1 0 1
3 011 1 1 1 2
4 100 2 1 0 1
5 101 2 1 1 2

Edge Cases & Common Mistakes

Watch out for these pitfalls:

  • dp[0] needs no work. Zero has no 1 bits, and an array of zeros already says so — but the array has to be n + 1 long, not n.

  • i >> 1 is always already written. Shifting right halves the number, so the cell being read is to the left of the cell being written. That is what makes one forward pass enough.

  • A power of two resets the count. 8 is 1000 and dp[8] = 1, right after dp[7] = 3. If your counts only ever climb, you are counting something else.

Solution

One pass, reusing an earlier answer for every number — the lines light up as the figure above steps.

Counting Bits Code
1var countBits = function(n) {
2 const dp = new Array(n + 1).fill(0);
3 for (let i = 1; i <= n; i++) {
4 const half = dp[i >> 1];
5 dp[i] = half + (i & 1);
6 }
7 return dp;
8};

The approach, step by step

  1. Allocate and set the base

    Make an array of n + 1 zeros. dp[0] is already correct: zero has no 1 bits.

  2. Walk upward once

    For each i from 1 to n, read dp[i >> 1] — the count for i without its last binary digit.

  3. Add the dropped bit back

    Add i & 1, which is that last digit, and store the result in dp[i].

Frequently asked questions

Why does dp[i] = dp[i >> 1] + (i & 1) work?

Shifting i right by one drops its last binary digit and keeps every other one, so i >> 1 has exactly the bits of i minus that last digit. Adding i & 1 puts the dropped digit back. Since i >> 1 is always smaller than i, its count is already computed.


How is this faster than counting each number separately?

Counting the bits of one number takes O(log n) on its own, so doing it for every number up to n is O(n log n). Reusing an earlier answer makes each number O(1), and the whole array O(n).


Does the same trick work with i - (i & -i) or i & (i - 1)?

Yes. i & (i - 1) clears the lowest set bit, so dp[i] = dp[i & (i - 1)] + 1 is an equally valid one-pass recurrence. The shift version is usually preferred because the relationship to the binary digits is easier to see.

Applying for software engineering roles? Free, no sign-up:

AI resume checker — match your resume to the job description