【4.15】求二进制数中1的个数【每日一题】

【4.15】求二进制中1的个数。例如,10=1010,1的个数为2。【每日一题】

此题主要考查位运算,当然不会用位运算的人可能会这么写:

1.可能是最笨的方法了

int numOfOne(unsigned num) {
    int count = 0;
    while (num) {
        count += num % 2;
        num /= 2;
    }
    return count;
}


使用位运算的原因是位运算比乘法要快,这是与计算机的硬件实现相关的。下面是使用位运算中的一种比较弱多解法,好处是逻辑清楚,易懂。


2.用位运算来代替方法1中的除法和取模运算

int numOfOne(unsigned num) {
    int count = 0;
    while (num) {
        count += num & 1;
        num >>= 1;
    }
    return count;
}


方法2中的方法已经比方法1中的方法好很多了,但是有没有更好的方法呢?下面是编程之美中给出的方法


3.只用一次位运算

int hammingWeight(uint32_t n) {
    int count = 0;
    while (n) {
        n = n & n - 1;
        ++count;
    }
    return count;
}


这个方法中,每次循环仅用了一次位运算,从这里已经比方法2省了一次位运算,另外,我们可以发现如下规律:

  1. 当n不为0时,n-1总是从把n中最后一个1(二进制位)改为0(二进制位),同时将其后的所有位置0,而与此同时对于前面的所有位,n与n-1每一位均相同,因此&操作并不会改变前面所有位数的值。这样n & (n - 1)的最终效果是把n的最后一个1置0,因此我们给count加1
  2. 在每次循环时,总是找到n的最后一个1去操作,因此跳过了n所有二进制位中后面的连续的多个0位,可以有效减少循环执行次数
如前所述,方法3中循环可以跳过二进制位中的0位以减少循环执行次数,我们举例如下:

【例】 对于十进制数100,其二进制表示位1100100
  • 对于方法2,循环将执行7次
次数执行前num值执行后num值执行后count值
111001001100100
2110010110010
31100111001
411001101
5110111
61112
7103


  • 对于方法3,循环执行3次
次数执行前n值执行后n值执行后count值
1110010011000001
2110000010000002
3100000003


从例子中可以看出,方法3可以显著减少循环的执行次数。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值