请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。例如,把9表示成二进制是1001,有2位为1。因此,如果输入9,则该函数输出2。
class Solution {
public:
int NumberOf1(int n) {
int count=0;
while(n){
if(n&1)
++count;
n=n>>1;
}
return count;
}
};
问题1:上述整数右移一位和把整数除以2在数学上是等价的,但是不能简单替换。因为,除法的效率比移位运算要低得多。
问题2:如果输入一个负数,那么移位后高位补1,那么最终这个数字就会变成0xFFFFFFFF从而陷入死循环。
方法2:为了避免死循环,我们可以把n和1做运算,判断n的最低位是不是为1。接着把1左移移位得到2,再和n做&运算。就能判断n的次低位是不是1…..如此反复。
class Solution {
public:
int NumberOf1(int n) {
int count = 0;
unsigned int flag = 1;
while (flag){
if (n&flag)
++count;
flag = flag << 1;
}
return count;
}
};
上面的解法中,循环的次数等于证书的位数,32位的整数需要循环32次。
方法3:把一个数减去1,再和原整数做&运算,会把该整数最右边的1变成0。那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。
class Solution {
public:
int NumberOf1(int n) {
int count=0;
while(n)
{
++count;
n=n&(n-1);
}
return count;
}
};
把一个整数减去1之后再和原来的整数做&运算,得到的结果相当于把整数的二进制表示中最右边的1变成0。
相关题目
- 用一条语句判断一个整数是不是2的整数次方。
if(!(n&(n-1)))
- 输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n。
int Times(int m,int n)
{
int count=0;
int xor=m^n;
while(xor)
{
++count;
xor=xor&(xor-1);
}
}