题目描述:
输入一个整数,输出该数二进制表示中1的个数,其中负数用补码表示。
注意:整数在计算机中本身就是以二进制形式存储的。
主要使用的是位运算。
补码的移位:
左移:正负数均是在右边补0;
右移:正数是在左边补0,负数是在左边补1。
方案1:
依次将1左移,与该数做&运算。
class Solution {
public:
int NumberOf1(int n) {
int count = 0;
int tmp = 1;
while(tmp){
if(n & tmp){
count++ ;
}
tmp = tmp << 1;
}
return count;
}
};
运行时间:4ms
占用内存:480K
方案2:该数与1做&运算,但要注意循环条件,因为当为负数时,负数右移左边补1,所以可能陷入无限循环,因此需要控制其位数。该方案需要一共执行判断32次。
class Solution {
public:
int NumberOf1(int n) {
int count = 0;
int tmp = 0;
while(tmp < 32){
if(n & 1){
count++ ;
}
n = n >> 1;
tmp++;
}
return count;
}
};
运行时间:3ms
占用内存:384K
方案3:x&(x-1)可以将整数的最右边的1变为0,根据这个,我们只需循环判断x = x&(x-1) 是否为0,即可统计1的个数。该方案相比方案2而言减少了循环的次数。
eg:-5二进制中1的个数。
x | x&(x-1) |
0101 | 0101 & 0100 = 0100 |
0100 | 0100 & 0011 = 0000 |
class Solution {
public:
int NumberOf1(int n) {
int count = 0;
while(n){
count++;
n = n & (n-1);
}
return count;
}
};
运行时间:3ms
占用内存:480K
方案4:使用辗转相除法。
注意:该方案只能用于正数,不能用于负数。
eg: -1 % 2 != 1,count =0;但实际上-1的二进制中有32个1。
class Solution {
public:
int NumberOf1(int n) {
int count = 0;
while(n){
if(n % 2 == 1){
count++;
}
n = n/2;
}
return count;
}
};
参考链接:
http://www.cnblogs.com/AndyJee/p/4630568.html
https://blog.csdn.net/zhao_miao/article/details/79747664