經典 Brian Kernighan 演算法:n &= (n-1) 每次清除最低位 1,迴圈次數等於 1 的個數。
#include <stdio.h>
int popcount(int n) {
int count = 0;
while (n) {
count++;
n &= (n - 1);
}
return count;
}
int main() {
printf("10 (1010) -> %d\n", popcount(10)); // 2
printf("0 -> %d\n", popcount(0)); // 0
printf("-1 (全1) -> %d\n", popcount(-1)); // 32 (32-bit)
return 0;
}
| 方法 | 時間複雜度 | 特點 |
|---|---|---|
| 逐位檢查 | O(32) | 固定 32 次迴圈,分支預測友好 |
| 查表法 (8-bit) | O(4) | 4 次查表+移位,需 256 Byte 表 |
| Kernighan | O(popcount) | 1 的個數越少越快,無分支 |
| 硬體 POPCNT | O(1) | 單指令,現代 CPU 普遍支援 |
__builtin_popcount (unsigned int), __builtin_popcountll (unsigned long long)。std::popcount (<bit>)。Integer.bitCount()。int.bit_count() (3.10+)。int count_zeros(int n) {
return 32 - popcount(n); // 32-bit
}
popcount(n) == 1。