标签:方法 源码 img -- 结果 4行 lazy stat 操作
示例 1:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1‘。
示例 2:
输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 ‘1‘。
示例 3:
输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 ‘1‘。
本题主要考察的是位运算操作,作为一个搬砖的码农,解法较为普通,代码如下:
public int hammingWeight(int n) {
//为0则直接返回
if(n == 0) {
return 0;
}
int bit = 1;
int count = 0;
//从n的低位到高位,通过循环,bit每次左移1位,即可将n的每位与 1 做一次&运算
while(n!= bit) {
//如果bit跟n的&运算位1,则表示当前位状态位1
if((bit&n) == bit){
count++;
}
//每次循环将n该位置0,以便判断终止条件
n &= bit^(-1);
//bit左移
bit<<=1;
}
return count+1;
}
这个解法的效率也不是很低,在leetcode上耗时也能击败99.5%的用户。然而在jdk源码中也有一个获取二进制1的个数的方法,看到这种解法后,不得不感叹大佬们在算法上的造诣。
源码奉上:
public static int bitCount(int i) {
// HD, Figure 5-2
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;
}
简简单单的6行代码-----------当然,只是步骤简单,理解起来并不是那么的容易啊??几行代码,看了我几个小时,才能懂整个过程的来龙去脉。下面谈谈我对这些代码的理解。
0x55555555:0101 0101 0101 0101 0101 0101 0101 0101
0x33333333:0011 0011 0011 0011 0011 0011 0011 0011
0x0f0f0f0f:0000 1111 0000 1111 0000 1111 0000 1111
0x3f: 0000 0000 0000 0000 0000 0000 0011 1111
>>>:无符号右移,以0补位
i = i - ((i >>> 1) & 0x55555555);
意为将 i 的32位分成16组。通过将参数i 右移1位,与0x55555555 作&运算,使右移后的奇数位置零,记为i2。再将原i的值减去i2,得到结果:每组值为每组1得个数(每组2位)。
以i=1111 1111 1111 1111 1111 1111 1111 1111(32位1)为例:
经过第1行代码运算后,16组每组1个数都为2个。
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
第2行代码与1行类似,将32位分成8组,每组4位,计算结果为每4位一组的1的个数。
当前 i的值为:i= 1010 1010 1010 1010 1010 1010 1010 1010;
通过i & 0x33333333 求得每组低2位 1的个数,(i >>> 2) & 0x33333333 求得每组高2位1的个数,然后相加重新赋值,结果为每4位1的个数。
i = (i + (i >>> 4)) & 0x0f0f0f0f;
将32位分成4组,每组8位,计算结果为每8位一组的1的个数。
当前 i的值为:i=0100 0100 0100 0100 0100 0100 0100 0100 ;
i + (i >>> 4) 计算每组高4位和低4位1的各种之和,并将高4位置零,然后重新赋值。
i = i + (i >>> 8);
将32位分成2组,每组16位,计算结果为每16位一组的1的个数。
当前 i的值为:i=0000 1000 0000 1000 0000 1000 0000 1000 ;
i + (i >>>8) 计算每组高8位和低8位1的各种之和,然后重新赋值。
i = i + (i >>> 16);
当前 i的值为:i=0000 0000 0001 0000 0000 0000 0001 0000;
i + (i >>>16) 计算每组高16位和低16位1的各种之和,然后重新赋值。
return i & 0x3f;
i & 0x3f 的值为 截取i低6位的值,将高26位置零。由于int型1的个数最多32个,即最多6位可表示。因此低6位的值即为i的1的个数,将其返回,求得结果。
标签:方法 源码 img -- 结果 4行 lazy stat 操作
原文地址:https://www.cnblogs.com/endless-daydream/p/13904608.html