【算法】布赖恩·克尼根算法——天才算法求二进制中1的个数

题目背景

做leetcode第461题汉明距离的时候,发现一个很骚的求1的个数的算法,大呼牛逼!

在这里插入图片描述
其实题目本身思路不难,就是求异或然后算1个个数,只是没有想到还可以用这么骚的方式来求。

布赖恩·克尼根算法思路

是否可以像人类直观的计数比特为 1 的位数,跳过两个 1 之间的 0。例如:10001000。

这是布赖恩·克尼根位计数算法的基本思想。该算法使用特定比特位和算术运算移除等于 1 的最右比特位。

当我们在 number 和 number-1 上做 AND 位运算时,原数字 number 的最右边等于 1 的比特会被移除。

基于以上思路,通过 2 次迭代就可以知道 10001000 中 1 的位数。

class Solution:
    def hammingDistance(self, x, y):
        xor = x ^ y
        distance = 0
        while xor:
            distance += 1
            # remove the rightmost bit of '1'
            xor = xor & (xor - 1)
        return distance

巧妙之处

因为做了减1之后:

  1. 最右边的1必然必成0
  2. 最右边的1右边的所有0必然变成1

同时:

  1. AND操作对左边的数没有影响
  2. AND操作使得每次抹掉最右边1个0

所以只要结果中不全为0(反过来,即只要还有1存在),就可以一直进行上面的减1和AND操作,每操作1次就代表有一个1,所以就巧妙地求出了1的个数

通过二进制算数的特点来求1个个数,真是太骚了,这得对二进制的理解多么深刻才行。。天才。。

猜你喜欢

转载自blog.csdn.net/weixin_38705903/article/details/109255076
今日推荐