Golang-位运算(一)大学小用:计算一个二进制数字有多少1?

610 阅读1分钟

熟悉的有三种解法:

1.程序内置的方法:

一般我们的语言这种基本的函数都是有的,比如:

  • golang: bits.OnesCount

  • C/C++: __builtin_popcount

  • Java: Integer.bitCount

复杂度分析

  • 时间复杂度:O(1) 不同语言的实现方法不一,我们可以近似认为其时间复杂度为 O(1)O(1)。
  • 空间复杂度:O(1)

2. 最基本的轮询方法

// s 为我们的目标数字
for  s > 0  {
  			// 位移后和1与运算,如果为1那最低一位就是1
        ans += s & 1
  			// 向右移一位,最低位舍弃
        s >>= 1
}

复杂度分析

  • 时间复杂度:O(log C),其中 C 是元素的数据范围。

  • 空间复杂度:O(1)

3.Brian Kernighan 算法

在方法二中,对于 s=10001100 的情况,我们需要循环右移 8 次才能得到答案。而实际上如果我们可以跳过两个 1 之间的 0,直接对 1 进行计数,那么就只需要循环 3 次即可。

我们可以使用Brian Kernighan 算法进行优化,具体地,该算法可以被描述为这样一个结论:记 f(x) 表示 x 和 x−1 进行与运算所得的结果那么 f(x) 恰为 x 删去其二进制表示中最右侧的 1 的结果。

在这里插入图片描述

Go代码实现:

for s > 0  {
  			// 累加的技术
        ans++
  			// 算法核心
  			s &= s - 1
}

复杂度分析

  • 时间复杂度:O(1),在 Java 中 Integer 的大小是固定的,处理时间也是固定的。 但是该方法需要的迭代操作更少。
  • 空间复杂度:O(1),使用恒定大小的空间。

来源

汉明距离 | 力扣(LeetCode) [汉明距离 | 题解(LeetCode)](