【算法】布赖恩·克尼根算法——天才算法求二进制中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个个数,真是太骚了,这得对二进制的理解多么深刻才行。。天才。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值