對於無符號整數 x:
(x & (x - 1)) == 0 且 x != 0。x &= (x - 1),每次消除最低位的 1,循環次數即為 1 的個數。x & (x-1) 能消除最低位 1?x = xxxx 1 0000 (最低位 1 後面全 0)
x - 1 = xxxx 0 1111 (借位:最低位 1 變 0,後面全變 1)
x & (x-1)= xxxx 0 0000 (最低位 1 被清零,高位不變)
x 只有 **一個 1**(即 2 的冪次),則 x & (x-1) == 0。x 有 **多個 1**,結果非零,且最低位 1 被清除。#define IS_POWER_OF_TWO(x) ((x) != 0 && ((x) & ((x) - 1)) == 0)
// 或函數版
int isPowerOfTwo(unsigned int x) {
return x && !(x & (x - 1));
}
// 測試
int main() {
unsigned int m = 512; // 2^9
printf("%d\n", isPowerOfTwo(m)); // 1 (真)
m = 513;
printf("%d\n", isPowerOfTwo(m)); // 0 (假)
return 0;
}
int countOnes(unsigned int x) {
int count = 0;
while (x) {
x &= (x - 1); // 清除最低位 1
count++;
}
return count;
}
// 時間複雜度:O(k),k 為 1 的個數,最壞 O(32) = O(1)
| 方法 | 時間複雜度 | 特點 |
|---|---|---|
| 查表法 (8-bit/16-bit 分段) | O(1) 固定查表 | 最快,需額外 256/65536 字節表 |
| 並行計數 (SWAR) | O(log 32) = 5 步 | 無分支,適合 SIMD/GPU |
| Brian Kernighan (x &= x-1) | O(k) | 代碼極短,1 越少越快,無額外空間 |
| 逐位移位檢查 | O(32) | 最慢,教學用 |