汉明距离
本文转载自文章“汉明距离及其高效计算方法”,记录笔记。
汉明距离#
在信息论中,两个等长字符串之间的汉明距离(英语:Hamming distance)是两个字符串对应位置的不同字符的个数。换句话说,它就是将⼀个字符串变换成另外⼀个字符串所需要替换的字符个数。
对于两个数字来说,汉明距离就是转成⼆进制后,对应的位置值不相同的个数。例如,假设有两个⼗进制数 a=93 和 b=73 ,如果将这两个数⽤⼆ 进制表⽰的话,有 a=1011101 、 b=1001001 ,可以看出,⼆者的从右往左数的第3位、第5位不同(从1开始数),因此, a 和 b 的汉明距离是2。
汉明距离是以理查德·卫斯⾥·汉明的名字命名的。在通信传输过程中,累计定长⼆进制字中发⽣翻转的错误数据位,所以它也被称为信号距离。 汉明距离在包括信息论、编码理论、密码学等领域都有应⽤。
- 信号距离,就是传输前后信息若发生翻转,出现错误,则出现的错误数据位数是信号距离。
如何计算#
既然⽬标是计算两个⼆进制数的对应位的值不同的个数,我们⾃然会联想到异或运算。因为异或运算的原则就是相同为0,不同为1。因此,通过 计算
例如:
一眼就能看出
中有2个1,那计算机怎么识别呢? 即如何统计
的⼆进制格式中 1 出现的次数?
方法1#
我们可以将
例如:
程序实现:
def hammingDistance(x, y):
xor = x ^ y #先异或
distance = 0
# 每次右移,最左边都会补零,因此截⽌条件是xor已经是⼀个零值了
while xor:
if xor & 1:
distance = distance + 1 #检测到1
xor = xor >> 1 # 右移
return distance
方法2#
上述算法是⼀个很符合直觉的算法,但需要遍历所有的位。这⾥给出⼀个更精巧的思路,可以提⾼性能。
布莱恩.尼克根算法
我们先观察如下⼀个现象:对于任意⼀个⾮零的⼆进制数 a (将其看作⽆符号数),考虑 a 和 a-1 的关系。由于 a ⾮零,那么 a 中总有⼀些位为1 。假设 a 中最低位的 1 处于从右向左数的第 N 位。那么, a 的第 N 位以及第 N 位以后的每⼀位的值和 a-1 的第 N 位及第 N 位以后的每⼀位 的值均不同。
举例,我们以8位数来描述。假设 a=10010000 ,根据上述描述,从右往左数的第⼀个 1 出现在第 5 位,那么有 N=5 。同时可 以计算出 a-1=10001111 ,可以看到,从第 N 位开始(从右开始), a 的后缀是 10000 ,⽽ a-1 的后缀是 01111 。满⾜上述描述的现象。
进⼀步地,我们可以发现,如果对 a 和 a-1 进⾏与操作,就会直接消去位于最后⼀位,也就是第 N 位的 1 。还以上⾯的 a 为例, a & (a1)=10000000 。可以看到,我们不需要遍历,⽽是通过⼀次运算,就可以把 a 中的最后⼀个 1 消掉。如果我们⼀直重复这项操作,那么 a ⾥有多少 个 1 ,我们就仅需要多少次 a & (a-1) 的操作,就能把 a 化为 0 了。⽽这个操作的次数正是我们所要求的。
再举例看⼀下这个过程。假设⼀个数 x=10010001 ,那么有:
x = 10010001, x-1 = 10010000, y = x & (x - 1) = 10010000
y = 10010000, y-1 = 10001111, z = y & (y - 1) = 10000000
z = 10000000, z-1 = 01111111, z & (z - 1) = 00000000
x ⾥有 3 个 1 ,经过上述过程,只需要 3 次操作,就能得知 x 中有多少个 1 。⽽如果使⽤遍历的⽅法的话,需要 8 次操作才⾏。
改进的求汉明距离的代码如下:
def hammingDistance(x, y):
xor = x ^ y #先异或
distance = 0
while xor:
distance = distance + 1
xor = xor & (xor - 1)
return distance
这也是leetcode上的⼀道热题#461,⼤家可以参考。
- 可以看出方法2更快。
作者:Hang Shao
出处:https://www.cnblogs.com/pam-sh/p/16663399.html
版权:本作品采用「知识共享」许可协议进行许可。
声明:欢迎交流! 原文链接 ,如有问题,可邮件(mir_soh@163.com)咨询.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
2021-09-06 C++:随机数生成
2021-09-06 C++:typedef 与 #define 的区别