二进制中1的个数

“对于一个字节(8bit)的无符号整型变量,求其二进制表示中1的个数,要求算法的执行效率尽可能的高”

(1)第一种方法是通过对这个数字N求余数,如果求余后有余,那么表示当前位置有一个1,否则便没有。然后N=N/2。其实就是相当于从低位向高位扫描,每除以2,就是去掉低一位,若该位为1,那么n%2=1.

  int Count( int n)
{
    int  num=0;
    while(n)
    {
      if(v%2==1)
      {
       num++;
      }
      n=n/2;
     }
     return num;
}

(2)第二种方法其实思想和第一种方法差不多,只不过N=N/2 改用移位来运算:N>>=1;然后用N 同1进行“与”运算,来判断末尾是否为1,如果N的二进制形式末尾有1,则“与”结果为1,否则为0. 利用N和0x01做与操作,来判断低位是0还是1.然后把N右移1位。想法和第一钟方法是一样的,就是利用了与操作和移位来实现,效率要比方法一高一些。

int Count( int n)
{
    int  num=0;
    while(n)
   {
       num+=n &0x01;
       n>>=1;
    }
    return num;
}

(3)第三种方式,比较巧妙。方法(1)和(2)的时间复杂度都为O(log2N)(以2为底的幂运算),因为N是以2的指数速度递减的。

 如何让算法的复杂度只与“1”的个数有关。算法如下:每次做n&(n-1),n二进制中1的个数就减少1个。若n&(n-1)=0,说明已经没有1了。

 印象中在《程序员面试宝典》有这个思路。

 int Count( int n)
{
    int  num=0;
    while(n)
    {
        n &=(n-1);
        num++;
     }
     return num;
}

(4)效率最高应该是第五种方法,呵呵,他比较变态的将“0-255”的每个数二进制形式的“1”的个数保存成了一个数组,然后直接返回个数,时间复杂度为O(1).

int table[]=
{
0,1,1,2,1,2,2,3,1,2,
2,3,2,3,3,4,1,2,2,3,
2,3,3,4,2,3,3,4,3,4,
4,5,1,2,2,3,2,3,3,4,
2,3,3,4,3,4,4,5,2,3,
3,4,3,4,4,5,3,4,4,5,
4,5,5,6,1,2,2,3,2,3,
3,4,2,3,3,4,3,4,4,5,
2,3,3,4,3,4,4,5,3,4,
4,5,4,5,5,6,2,3,3,4,
3,4,4,5,3,4,4,5,4,5,
5,6,3,4,4,5,4,5,5,6,
4,5,5,6,5,6,6,7,1,2,
2,3,2,3,3,4,2,3,3,4,
3,4,4,5,2,3,3,4,3,4,
4,5,3,4,4,5,4,5,5,6,
2,3,3,4,3,4,4,5,3,4,
4,5,4,5,5,6,3,4,4,5,
4,5,5,6,4,5,5,6,5,6,
6,7,2,3,3,4,3,4,4,5,
3,4,4,5,4,5,5,6,3,4,
4,5,4,5,5,6,4,5,5,6,
5,6,6,7,3,4,4,5,4,5,
5,6,4,5,5,6,5,6,6,7,
4,5,5,6,5,6,6,7,5,6,
6,7,6,7,7,8
};
int Count(int n)
{
  return table[n];
}

问题扩展:

给定两个正整数A和B,问把A变成B需要改变多少位?也就是A和B的二进制中有多少位是不同的?

解决思路:先让A和B做异或操作(A^B),A和B不同的位通过异或操作的1,然后统计A^B中1的个数就可以了。

测试程序如下:

int main()
{
BYTE c;
int a;
while(cin>>a)
{
       c=(BYTE)a;       //把输入数字转为BYTE型。当然如果统计的不是一个字节的1的个数,那么不用(BYTE)a,直接调用Count() 就可以了。
       cout<<Count(c)<<endl;
}
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值