1、题目
请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制是1001,有2位是1。因此如果输入9,该函数输出2。
2、普通解法
借助一个flag分别判定整数的每一位是否是1,不改变原来整数的值,只通过左移操作改变flag二进制形式中1的位置,再分别与整数的对应位置与,来判断整数的哪一位为1。
int NumberOf1(int n){
int count = 0;
unsigned int flag = 1;
while(flag){
if(n & flag)
count++;
flag = flag << 1;
}
return count;
}
3、优化版算法
当一个数不为0时,它的二进制形式中肯定有一位为1;
当该整数末位为1,给该整数减一时,末位由1变为0,其他位保持不变(例:1101–>1100);
当该整数末位为0,最后一个1的位置为m,那么减去1时,第m位由1变成0,m位之后由0变成1,m位之前保持不变(例:111000–>110111);
再将该整数和它减去1的结果作位与运算,相当于把它最右边的1变成0。
把一个整数减去1,在和原整数做与运算,会把该整数的最右边一个1变成0。那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。
int NumberOf1(int n){
int count = 0;
while(n){
count++;
n=(n-1)&n;
}
return count;
}
4、相关题目
- 用一条语句判断一个整数是不是2的整数次方。一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是1,其他所有位都是0。根据前面的分析,把这个整数减去1之后再和它自己做与运算,这个整数中唯一的1就会变成0。
- 输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n。可以分为两步解决这个问题:第一步求这两个数的异或,第二步统计异或结果中1的个数。