常规解法:
思路:
将这个数与1 按位与 ,然后,将这个二进制数右移,循环计算。
理解:
由于1的二进制位除了第一位全是0,所以计算的结果除第一位,其他位都是0。
当这个数的第一位为1时,结果为1;当这个数的第位为0,结果为0.
错误代码:
\\函数
int count_1(int n)
{
int count = 0;
while(n)
{
if(n&1 == 1)
count++;
n >>= 1;
}
return count;
}
错误原因:">>"在不同编译器下执行的可能是算数右移(高位补符号位)或逻辑右移(高位补0),当输入为负数,算数右移会一直补1,陷入死循环。
解决方法:控制二进制位右移的次数。
正确代码:
\\函数
int count_1(int n)
{
int count = 0;
int i = 0;
for (i = 0;i < 32;i++)
{
if ((n >> i) & 1 == 1)
count++;
}
return count;
}
进阶解法:
思路:
让这个数n与(n-1) 按位与,把这个结果赋值给n后,继续循环计算,直到n的值是0。
理解:
第一种情况:n的二进制最低位是1
n-1使n的最低位变为0,其他位不变。
n与(n-1)按位与的结果相当于让n最低位的1变为0,其他位不变得到的一个二进制数。
当把这个结果赋值给n后,再对n与(n-1)按位与时,就是接下来的第二种情况。
第二种情况:n的二进制最低位是0
与第一种情况不同,n-1是让在n所有是1的位中,最低位的1借位到更低位,而变为0。
n与(n-1)按位与的结果就相当于将n的二进制数中的第一个1去掉。
代码:
\\函数
int count_1(int n)
{
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}