剑指offer(11)——二进制中1的个数

119 阅读2分钟

这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战

题目

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数

示例 1:

输入:n = 11 (控制台输入 00000000000000000000000000001011)
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'

思路 number&= number-1 -----只与二进制中1的位数相关的算法 逐个数的方法效率是比较低下的,因为它把每一位都考虑进去了,没有进行筛选,一个劲的蛮干。

现在,我们可以考虑每次找到从最低位开始遇到的第一个1,计数,再把它清零,清零的位运算操作是与一个零(任何数与零都等于零)。 好了,现在分析下逐个数算法的性能。不难看出,对于任何一个整数n(对应的二进制数有 位),它都要进行 次判断。可以说,算法效率比较低,每一位都进行了判断。

当然,我们不能排斥效率低的算法,任何算法,没有绝对的优越,都是在比较中体现。 但是在有1的这一位与零的操作要同时不影响未统计过的位数和已经统计过的位数,于是可以有这样一个操作number&= number-1。

这个操作对比当前操作位高的位没有影响,对低位则完全清零。

拿6(110)来做例子,

第一次 110&101=100,这次操作成功的把从低位起第一个1消掉了,同时计数器加1。

第二次100&011=000,同理又统计了高位的一个1,此时n已变为0,不需要再继续了,于是110中有2个1。 ————————————————

代码


//   n & (n - 1) 可以去掉末尾的1
//   因为 n - 1 会借掉 n 的末位的 1
  
//   举例说明:
//   12: 1100   11: 1011
  
//   12 & 11 = 1 1 0 0 
//           & 1 0 1 1
//             1 0 0 0
  
//   '&': 对位都为 1 则结果为 1,否则为 0

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