n & (n − 1) subtracting 1 flips the lowest 1 and the zeros below it · AND keeps a bit only where both rows have 1
Cleared so far one loop round per 1 bit, the zeros cost nothing
public int hammingWeight(int n) { int res = 0; while (n != 0) { n &= n - 1; // drop the lowest 1 bit res++; } return res;}
- n
- —
- n − 1
- —
- res
- 0
Why it works
- Brute force checks every bit:
res += n & 1; n >>>= 132 times (orInteger.bitCount(n)). O(32) per call, even for a number with a single 1. - n − 1 flips the lowest 1 and every 0 below it. Borrowing in binary turns
…1000into…0111, and leaves the higher bits alone. ANDing with n keeps the higher bits and zeroes the whole flipped tail, so exactly one 1 disappears per round. - O(k) rounds for k ones, at most 31 for a 31-bit number, O(1) space. The loop jumps straight from one 1 to the next, skipping runs of zeros.
- Pitfall: the sign bit. A Java
intis 32 bits and LeetCode passes the input as unsigned bits, soncan arrive negative.n &= n - 1still reaches 0. The shifting version needs>>>:>>copies the sign bit and never reaches 0 for a negativen. - Related:
n & (n − 1) == 0tests for a power of two (231). Counting Bits (338) reuses the same idea as a DP:bits[i] = bits[i & (i − 1)] + 1.