Counting set bits
Count how many bits are 1 in a number by clearing the lowest set bit until nothing is left, or build counts for every number from smaller ones.
O(k) for one number, O(n) for the tableSpace O(1) and O(n)4 practice problemsStep-through pictureThe idea
The number of 1 bits in a number is called its population count, or popcount. 13 is 1101, so its popcount is 3. If a number is a mask of flags, its popcount is how many flags are on.
The slow way checks all 32 bits one by one. A faster way uses x & (x - 1), which clears the lowest 1 bit. Repeat it until x is 0, and count the steps: the loop runs once per 1 bit, not 32 times.
To get popcounts for every number from 0 to n, reuse earlier answers. i >> 1 is i with its last bit removed, and that smaller number's count is already known. So bits[i] = bits[i >> 1] + (i & 1).
An everyday example
Blowing out candles from the right
A row of candles stands on a cake, some lit and some not. You count the lit ones by always blowing out the lit candle furthest to the right and adding one to your count. When no candle is lit, your count is the answer. You never waste a breath on a candle that was already out.
| In the example | In the code |
|---|---|
| The row of candles | the bits of x |
| Blowing out the rightmost lit candle | x &= x - 1 |
| Adding one to your count | count++ |
| No candle is lit | x === 0 |
From the slow way to counting set bits
- Start with the obvious way: look at all 32 positions. For
kfrom 0 to 31, add(x >>> k) & 1. That's always 32 steps, even forx = 1, which has a single 1 bit. - A little better: look at the last bit with
x & 1, then shift it away withx >>>= 1, untilxis 0. The loop now stops after the highest set bit: 8 steps for180(10110100). But it still visits every 0 bit below the top one. - Now notice what
x - 1does: it turns the lowest 1 bit into 0 and every 0 below it into 1, leaving higher bits alone. Sox & (x - 1)isxwith its lowest 1 bit removed. Repeating it jumps from one 1 bit straight to the next, so the loop runs once per 1 bit: 4 steps for180. - For every number from 0 to
n, reuse earlier answers.i >> 1isiwith its last bit removed, a smaller number whose count is already known, andi & 1is that last bit. Sobits[i] = bits[i >> 1] + (i & 1), one step per number. Those two loops are bit counting.
How it works
- Turn the input into an unsigned 32-bit value with
x = n >>> 0, so negative numbers count their two's complement bits. - While
xis not 0, clear its lowest set bit withx &= x - 1. - Add 1 to
counteach time. - Return
countwhenxis 0. - For every number up to
n: makebitswithn + 1zeros and fillbits[i] = bits[i >> 1] + (i & 1)forifrom 1 up.
Watch it run
This picture runs the code below on a real input. Press Step to move one step at a time, or Play to watch. The highlighted line is the one that just ran. Change the input to see other cases.
See every step at onceThe same run, laid out side by side
The code
Point at a note to light up the lines it explains.
function countBits(n) {let x = n >>> 0;let count = 0;while (x !== 0) {x &= x - 1;count++;}return count;}function countBitsUpTo(n) {const bits = new Array(n + 1).fill(0);for (let i = 1; i <= n; i++) {bits[i] = bits[i >> 1] + (i & 1);}return bits;}
How fast it is
| Time | O(k) for one number, O(n) for the table |
|---|---|
| Extra memory | O(1) and O(n) |
The loop runs once per set bit, k of them, at most 32. The table fills each entry with one addition from an earlier entry.
- Best case
O(1)n = 0, where the loop never runs, or a power of two, which needs one step. - Average case
O(k)One step per 1 bit,
kof them. Random 32-bit values have about 16 set bits, so about 16 steps. - Worst case
O(k)Every bit set:
-1is 32 ones, so 32 steps, the most possible. The table version isO(n)forn + 1numbers.
Common mistakes
- Shifting a negative number right with
>>in a loop likewhile (x) { count += x & 1; x >>= 1; }. The sign bit keeps coming back and the loop never ends. Use>>>. - Using
n.toString(2)on a negative number. It gives"-101", not the two's complement bits. Use(n >>> 0).toString(2). - Counting bits of numbers above
2^32with these operators. The high bits are dropped first; useBigIntfor larger values. - Forgetting brackets in
bits[i >> 1] + i & 1.+runs before&, so write(i & 1).
When to use it
Look for these clues in a problem:
- The problem asks how many bits are set, how many flags are on, or how many items a mask holds.
- You need the Hamming distance: the number of positions where two bit patterns differ, which is
popcount(a ^ b). - You need bit counts for every number in a range.
- Inputs are 32-bit integers, possibly negative, described in two's complement.
Check yourself
Answer each one in your head first, then open it.
How many times does the loop run for countBits(180)?
4, once per 1 bit in 10110100. The shifting version would take 8 steps and checking every position would take 32.
What does countBits(-8) return?
29. In 32-bit two's complement, -8 is 29 ones followed by three zeros.
Why can bits[i] safely use bits[i >> 1]?
i >> 1 is smaller than i, and the table is filled from small to large, so that entry is already final.
Why would while (x) { count += x & 1; x >>= 1; } never end for negative x?
>> copies the sign bit into the top, so a negative x stays negative and ends up as -1 forever. >>> brings in zeros and lets it reach 0.
Practice problems
Stuck on one? Tuto is in the playground too, and gives you hints, never the answer.
0 of 4 solved. Solve one to earn the bronze medal, half for silver, and all of them for gold.
Start practicingGo further
You don't need these to start practicing. Open one when you want more.
Why it works
The reasoning that makes it always right
countBits keeps one promise: count plus the number of 1 bits still in x equals the answer. At the start, count is 0 and x holds all the bits, so it's true.
Each step keeps it. Subtracting 1 changes the lowest 1 of x to 0 and every 0 below it to 1; higher bits stay the same. ANDing with the old x keeps the higher bits, and clears the lowest 1 and everything below it, which were 0 in x anyway. So exactly one 1 bit disappears while count goes up by 1. When x reaches 0, no bits are left, so count is the answer, and the loop ran exactly once per 1 bit, at most 32 times.
countBitsUpTo relies on how binary numbers are built: i is i >> 1 with one more bit, i & 1, written on the end. So the count for i is the count for i >> 1 plus that last bit. Since i >> 1 is smaller than i for every i >= 1, filling the table in increasing order means the entry it needs is always ready.
Going deeper
3 more ideas
Why x & (x - 1) clears one bit
Subtracting 1 changes the lowest 1 bit to 0 and every 0 below it to 1, and leaves the higher bits alone. ANDing with the original keeps the higher bits, clears the lowest 1 bit, and clears the bits below it, which were 0 anyway. So each step removes exactly one 1 bit.
Counting for every number at once
i >> 1 drops the last bit of i, and i & 1 is that last bit. So the count for i is the count for i >> 1, which is smaller and already filled in, plus its last bit. For i = 6 (110): bits[3] + 0 = 2. The whole table takes O(n) time.
Negative numbers in JavaScript
-1 is 32 ones in two's complement, so its popcount is 32. Without >>> 0, a loop that shifts with >> would copy the sign bit forever and never reach 0. The x &= x - 1 loop still works on the signed value, but starting from n >>> 0 makes the meaning clear. Math.clz32(x) (count leading zeros) is built into JavaScript, but there is no built-in popcount.
Work it by hand
Every step in a table, with why
Count the 1 bits of 180, then fill the table of counts for 0 to 6.
countBits(180), then countBitsUpTo(6)
| Step | Value | Binary | Computes | Result | What happens | Why |
|---|---|---|---|---|---|---|
| 1 | x = 180 | 10110100 | 180 >>> 0 | count = 0 | start | >>> 0 changes nothing for a positive number. It matters for negatives. |
| 2 | x = 180 | 10110100 | 180 & 179 | 176, count = 1 | clear lowest 1 | 179 is 10110011: the lowest 1 (worth 4) became 0 and the two 0s below it became 1. The AND gives 10110000. |
| 3 | x = 176 | 10110000 | 176 & 175 | 160, count = 2 | clear lowest 1 | 175 is 10101111. The AND clears the bit worth 16: 10100000. |
| 4 | x = 160 | 10100000 | 160 & 159 | 128, count = 3 | clear lowest 1 | 159 is 10011111. Four 0 bits were skipped in one step. |
| 5 | x = 128 | 10000000 | 128 & 127 | 0, count = 4 | loop ends | 127 is 01111111, which shares no bit with 128. x is 0, so countBits returns 4. |
| 6 | i = 1 | 1 | bits[0] + 1 | 1 | last bit is 1 | countBitsUpTo(6) starts with bits = [0, 0, 0, 0, 0, 0, 0]; bits[0] stays 0. |
| 7 | i = 2 | 10 | bits[1] + 0 | 1 | 2 >> 1 is 1 | 10 is 1 with a 0 added at the end, so it has the same count as 1. |
| 8 | i = 3 | 11 | bits[1] + 1 | 2 | 3 >> 1 is 1 | 11 is 1 with a 1 added at the end. |
| 9 | i = 4 | 100 | bits[2] + 0 | 1 | 4 >> 1 is 2 | Every power of two has a count of 1. |
| 10 | i = 5 | 101 | bits[2] + 1 | 2 | 5 >> 1 is 2 | bits[2] was filled two steps ago. |
| 11 | i = 6 | 110 | bits[3] + 0 | 2 | 6 >> 1 is 3 | The loop reaches n, so it returns the table. |
countBits(180) is 4, found in 4 steps instead of 32. countBitsUpTo(6) is [0, 1, 1, 2, 1, 2, 2], with one addition per number.
Compared with other ways
When to pick something else
| Approach | Time | Extra memory | Choose it when |
|---|---|---|---|
| Counting set bits | O(k) | O(1) | Counting one number's bits, especially sparse masks with only a few flags on. |
| Check all 32 positions | O(w) | O(1) | Only when you also need to visit each position, such as listing which bits are on. |
| Parallel counting with masks | O(1) | O(1) | Hot code that counts millions of values; it's harder to read, so wrap it in a named function. |
Table for every number up to n | O(n) | O(n) | You need the count for every number from 0 to n, such as every subset mask. |
Extra memory: O(1) for countBits: x and count. countBitsUpTo stores n + 1 counts, O(n).
How the steps grow
- Counting set bits, Check all 32 positions, Table for every number up to
nO(k) - Parallel counting with masks
O(1)
| Approach | n = 10 | n = 1,000 | n = 1,000,000 |
|---|---|---|---|
| Counting set bits | 10 | 1,000 | 1 million |
| Check all 32 positions | 10 | 1,000 | 1 million |
| Parallel counting with masks | 1 | 1 | 1 |
Table for every number up to n | 10 | 1,000 | 1 million |
Inputs that need care
5 tricky inputs
n = 0xis 0, the loop never runs, and it returns 0.countBitsUpTo(0)returns[0].- A negative number:
countBits(-8) -8 >>> 0is4294967288, which is 29 ones followed by000, so it returns 29. After the first stepxbecomes-16, because&returns a signed result, but thex !== 0test still works.countBits(-1)- All 32 bits are 1, so it returns 32 after 32 steps, the most the loop can ever take.
- A number above
2^32:countBits(2 ** 32 + 7) >>> 0drops the high bit, so it returns 3, the count for 7. UseBigIntandx &= x - 1nfor wider numbers.- A decimal:
countBits(7.9) >>> 0cuts off the fraction, so it counts the bits of 7 and returns 3.
Variations and follow-ups
Twists interviewers add
Parallel counting
A fixed series of masks adds neighboring bits in pairs, then in groups of 4, then 8: x - ((x >>> 1) & 0x55555555), then (x & 0x33333333) + ((x >>> 2) & 0x33333333), and so on. It always takes the same few steps, with no loop, and gives the same answers as countBits.
Lookup table
Store the counts for all 256 byte values once, then add the counts of the 4 bytes of a 32-bit number: table[x & 255] + table[(x >>> 8) & 255] + .... Four lookups, whatever the number.
Hamming distance
The number of positions where two numbers differ is countBits(a ^ b), because XOR leaves a 1 exactly where they differ. For 180 and 3, 180 ^ 3 is 183 (10110111), so they differ in 6 places.
Another table rule
bits[i] = bits[i & (i - 1)] + 1 also works: i & (i - 1) is i with its lowest 1 removed, a smaller number with exactly one fewer 1 bit.
In an interview
Spot it, explain it, answer follow-ups
- Spot it from "number of 1 bits", "Hamming weight", "how many flags are set", "Hamming distance between two numbers", or "counting bits for every number up to
n". - Explain
x & (x - 1)with a small example out loud: "12is1100,11is1011, and the AND is1000. The lowest 1 is gone, so the loop runs once per 1 bit." - Test 0, a power of two, -1, and a negative number like -8. Mention why the shifting version with
>>would never end for negatives. - The common follow-up is "counts for every number up to
ninO(n)". Answerbits[i] = bits[i >> 1] + (i & 1), and explain thati >> 1is always already filled.
Where frontend code uses it
The same idea in real UI code
- Counting how many permissions or feature flags are on in a mask, for a badge such as "3 of 8 enabled".
- Immutable data libraries such as Immutable.js use hash array mapped tries, which store a bitmap per node and use a popcount to find a child's position in a compact array.
- Comparing two state masks with
popcount(a ^ b)tells how many flags changed between renders or snapshots.