思路:将二进制的每一位依次与1作与运算, T=O(n)
,n为二进制位数。
public int bitCount(int i) {
int count = 0;
do {
if ((i & 1) == 1) {
count++;
}
i >>= 1;
} while (i > 0);
return count;
}
复制代码
思路:将整数减一后与原数作与运算,达到将原二进制最低位"1"重置为"0"的目的。此时 T=O(n)
,但n为二进制中"1"的个数。
public int countBit(int i) {
int count = 0;
while (i > 0) {
i = i & (i - 1); // 抹除二进制中最低位的1
count++;
}
return count;
}
复制代码
思路:先每两位一组统计二进制中的"1",然后每四位一组统计"1",接着是8位、16位和32位,最终再与 0x3f
作与运算,输出结果。如下图:
二进制 十进制
1 0 1 1 0 0 1 1 0 1 1 1 10 11 00 11 01 11
01 10 00 10 01 10 1 2 0 2 1 2
/ / / / / / / / / / / /
0011 0010 0011 3 2 3
/ / 3 / /
0011 0101 3 5
/ / / /
1000 8
2871的二进制中的1的位数计算过程
复制代码
public static int bitCount(int i) {
i = (i & 0x55555555) + ((i >>> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
i = (i & 0x0f0f0f0f) + ((i >>> 4) & 0x0f0f0f0f);
i = (i & 0x00ff00ff) + ((i >>> 8) & 0x00ff00ff);
i = (i & 0x0000ffff) + ((i >>> 16) & 0x0000ffff);
return i;
}
复制代码
其中16进制数对应二进制为:
| 16进制 | 二进制 |
|---|---|
| 0x55555555 | 01010101010101010101010101010101 |
| 0x33333333 | 00110011001100110011001100110011 |
| 0x0f0f0f0f | 00001111000011110000111100001111 |
| 0x00ff00ff | 00000000111111110000000011111111 |
| 0x0000ffff | 00000000000000001111111111111111 |
| 0x3f | 00111111 |
0b11: 0b01 + 0b01 = 0b10 = 2, 0b10: 0b00 + 0b01 = 0b01 = 1
。研究发现: 2=0b11-0b1,1=0b10-0b1
,可以减少一次位于计算: i = i - ((i >>> 1) & 0x55555555)
i = (i + (i >>> 4)) & 0x0f0f0f0f
i & 0x3f
优化原型算法后,就得到java中内置的bitCount()方法:
public static int bitCount(int i) {
i = i - ((i >>> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
i = (i + (i >>> 4)) & 0x0f0f0f0f;
i = i + (i >>> 8);
i = i + (i >>> 16);
return i & 0x3f;
}
复制代码