Bit Manipulation · 1 of 10
Count set bits in an integer
Count how many 1s a number has in binary, by knocking out the lowest 1 again and again.
- Simple way
- time O(log n)
room O(1) - Clever way
- time O(k)
room O(1)
The problem, simply
Every number is stored as a row of bits, 0s and 1s. A bit that is 1 is called a set bit.
You get a number n. Give back how many of its bits are 1. For example 13 is 1101, which has three 1s.
A story to remember it
Picture it
44 in bits is 101100. Bits 2, 3 and 5 are on, so the answer is 3.
- answer
Examples
A normal number
- In
n = 13- Out
3
13 is 1101. Three bits are on.
One lonely bit
- In
n = 16- Out
1
16 is 10000. The plain way checks 5 bits. The clever way finishes in 1 round.
All bits on
- In
n = 255- Out
8
255 is 11111111. Every one of the 8 bits is on, so both ways take 8 rounds.
Zero
- In
n = 0- Out
0
No bits are on. The loop never runs.
Negative one
- In
n = -1- Out
32
In a Java int, -1 is 32 ones. Code that loops while (n > 0) gives 0 here, which is wrong.
Way 1: the simple way
Check the last bit, then slide the number right, and repeat.
n & 1is 1 when the last bit is on. If so, add 1 to the count.- Slide everything one place right with
n >>>= 1. The old last bit falls off. - Stop when
nis 0.
class Solution {
public static int countSetBits(int n) {
int count = 0;
while (n != 0) {
count += n & 1; // add 1 if the last bit is on
n >>>= 1; // slide right, pulling in a 0 on the left
}
return count;
}
}How long it takes: one round for every bit up to the highest 1, O(log n), at most 32 rounds. Extra room: O(1).
Way 2: the clever way
The trick is n & (n - 1). It wipes out the lowest 1 of n and leaves every other bit alone.
Why? Taking 1 away from n finds the lowest 1, turns it into 0, and turns all the 0s under it into 1s. Everything above stays the same. So n and n - 1 agree above that spot and are opposite from that spot down. AND keeps only bits that are 1 in both, so the bottom part becomes all 0s.
- While
nis not 0, don = n & (n - 1)and add 1 to the count. - The count is the number of 1s, because each round removed exactly one.
Knock out the lowest 1 until nothing is left
01 / 08
n = 44 is 101100. We will count its 1s by blowing out one candle at a time, always the rightmost one that is lit.
- count
- 0
- looking now
- done
- answer
- rejected
- just added
class Solution {
public static int countSetBits(int n) {
int count = 0;
while (n != 0) {
n &= n - 1; // wipe out the lowest 1
count++;
}
return count;
}
}How long it takes: one round per set bit. If n has k ones, that is O(k), which is never worse than Way 1 and much better for numbers with few ones. Extra room: O(1).
Watch out for
- Writing
n & n - 1without thinking about order. In Java-happens before&, so it works, butn & (n - 1)is clearer. - Java has
Integer.bitCount(n)andLong.bitCount(n). Fine in real code, but interviewers want the loop. - For a
long, uselongeverywhere, and1Lif you build masks.
What interviewers ask next
- Count bits for every number from 0 to
n? Use a table:bits[i] = bits[i >> 1] + (i & 1). Each number is its half plus its last bit, so the whole table isO(n). - Can it be faster for many queries? Precompute the count for all 256 byte values, then answer any
intwith four lookups, one per byte. - How does
Integer.bitCountwork? It adds bits in pairs, then pairs of pairs, and so on, with masks like0x55555555and0x33333333. That is 5 steps for 32 bits, no loop. - Is a number a power of two? It is when it is above 0 and has exactly one set bit, which means
n & (n - 1) == 0.
Remember this
Grown-up words: lit candles are set bits, the count is the population count or Hamming weight, the plain way is a shift loop, and the candle trick is Brian Kernighan's algorithm.