题目描述:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
负数的补码:减一取反 或者 取反加一
int 类型的范围是-231 ~ 231-1
我的做法:麻烦还不对
class Solution { public: int NumberOf1(int n) { if(n == 0) return 0; int num = 0; int con = n; bool flag = false; if(n % 2 == 1) num++; n = n/2; if(num == 1) flag = true; while(n) { if(n % 2 == 1) num++; n = n/2; } if(con > 0) return num; else { if(flag) return 15-num+1+1; else return 15-num+1; } } };
正确解法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; } };
正确解法2:
class Solution { public: int NumberOf1(int n) { int count = 0; while (n != 0) { ++count; n = (n - 1) & n; } return count; } };
下面的代码可以吗?:
int NumberOf1(int n) { int count = 0; while(n) { if(n&1) { n>>1; count++; } } return count; }
不可以。当n为负数时,右移时在左边补1,这样就成了一个死循环,左边一直补1.
将右移一位换成除以2行吗?不好,位运算效率高
改正为正确解法1:。
解法1的循环次数为二进制的位数,优化为解法2,循环次数为二进制中1的个数。
解法1的循环跳出方式:
结论:一个数与一个数-1相与,得到的结果是正数的二进制最后一位的1变为0.