剑指offer系列——11.二进制中1的个数
Q:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
C:时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32M,其他语言64M
T:(不要用右移的方法做,要注意可能会有负数!!!)
第一种方法,整形数字在32系统占32位,由低位到高位,按位与1,即可统计出32位中1的个数。
int NumberOf1(int n) {
int count = 0;
for (int i = 0; i < 32; i++) {
if (n & 1)
count++;
n >>= 1;
}
return count;
}
第二种,这种方法hin神奇,通过二进制构数原理。
一个为n的数,在不为0的前提下,二进制至少有一个位数为1。设n二进制值总共有k位,n-1时,n最右边的1位设为i位,i位更改为0,i位右边(k-i)位的0位全部更改为1,i位左边(i-1)位所有位数不变。则n&(n-1)的值,1~(i-1)位同为1有m位,相与为1,有(i-1-m)位为0,相与为0;i~k位为相与位0,则n&(n-1)共有m位为1,n共有(m+1)位为1。
综上,n&(n-1)比n位数为1的个数少1.
流程图如下:(画的好丑……)
代码:
int NumberOf1(int n) {
int count=0;
while(n)
{
n=n&(n-1);
count++;
}
return count;
}
P.S. 我崩了两次……第一次是直接每位右移,但如果是负数,会导致进入死循环;
int NumberOf11(int n) {
int count = 0;
while (n) { //如果输入为负数,n=-1,进入死循环
if (n & 1)
count++;
n >>= 1;
}
return count;
第二次,既然如此,那就做n=-1的判断,但这种,如果是2的幂次方的负数,就会本身在-1处有一个1判断不到。
//例如输入-2,输出为1,但这个代码输出为0
int NumberOf11(int n) {
int count = 0;
while (n && n != -1) {
if (n & 1)
count++;
n >>= 1;
}
return count;
}