思路:将二进制的每一位依次与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; } 复制代码