思路:
1.右移原数字不可取,负数需要在左边添加1,会造成死循环。
则改成:首先把i和1做与运算,判断i的最低位是不是为1。接着把1左移一位得到2,再和i做与运算,就能判断i的次地位是不是1
循环的次数等于整数二进制的位数,32位的整数就需要循环32次。
int NumberOf1(int n){int cnt = 0;unsigned int flag = 1;//必须是unsigned,不然只有31位while(flag){if(n & flag == 1)cnt++;flag <<= 1;}return cnt;}
2.将一个数减1后,该数最右边的1将会变成0,而该位右边的0全变成1。将减1后得到的数和原数进行&运算,则包括该位在内的右边的数全都变成0(都不相同)。
有几个1就能进行几次以上的操作
int NumberOf1(int n) {int cnt = 0;//比如1100,减1之后是1011,&运算后是1000,有多少个1,就可以执行多少次这样的运算;//必须是n!=0,n可能是负数阿while(n != 0){n = n & (n - 1);cnt++;}return cnt;}
引申题
1.用一条语句判断一个整数是不是2的整数次方:n & (n - 1) == 0
一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是1,而其他所有位都是0
2.输入两个整数m和n,计算要改变m的二进制表示中的多少位才能得到n。
(1)m和n异或
(2)统计异或结果中1的位数
总结
把一个整数减去1之后再和原来的整数做位与运算,得到的结果相当于是把整数的二进制表示中的最右边一个1变成0。很多二进制的问题都可以用这个思路解决。
