方法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);
注意以上这两个移位