方法1:
经牛人发现n &= (n – 1)能清除n的最右边的1,
来自微软的一道面试题:计算返回值
#include <iostream>
#include <bitset>
using namespace std;
int fun(int n)
{
int count=0;
while (n)
{
count++;
n=n&(n-1);
}
return count;
}
int main()
{
int m, num;
cin>>m;
cout<<bitset<14>(m)<<endl;//输出14位二进制数m
num=fun(m);
cout<<num<<endl;
}
实际上就是计算二进制中1的个数,每次循环都把末位1置零。
x=9999 (10011100001111), 返回8.
方法2.平行算法
虽然时间复杂度不是很好,但很巧妙。先将n写成二进制形式,然后相邻位相加,重复这个过程,直到只剩下一位。
以217(11011001)为例,有图有真相,下面的图足以说明一切了。217的二进制表示中有5个1
辉爷在讲解《编程珠玑》位图排序时,扩展位操作,还讲到了统计二进制中1的个数问题,方法一样
tmp = NUM;
tmp = ((tmp&0xAAAA)>>1) + (tmp&0x5555);
tmp = ((tmp&0xCCCC)>>2 )+ (tmp&0x3333);
tmp = ((tmp&0xF0F0)>>4) + (tmp&0x0F0F);
tmp = ((tmp&0xFF00)>>8) + (tmp&0x00FF);
注意以上这两个移位