力扣(leetcode) 477. 汉明距离总和(暴力异或)(超详细步骤二维矩阵)

题目在这:https://leetcode-cn.com/problems/total-hamming-distance/

题目分析:

昨天是汉明距离。今天是昨天的升级版求好几个汉明距离的综合。

法一:

思路分析: 根据昨天的异或统计‘1’的方法。这道题很容易的就可以得到思路。直接暴力循环,

List = [4, 14, 2]
res = 0
for i in range(len(List)-1):
    for j in range(i+1,len(List)):
        temp = bin(List[i] ^ List[j])
        for k in range(len(temp)):
            if temp[k] == '1':
                res += 1
print(res)

这段代码没什么好说的,两层循环遍历列表里的所有数,然后异或找其中的‘1’。最后统计就行了,对于这个算法不太理解的可以去看一下我昨天的文章,里面有对这个算法的详细介绍。
昨天的链接:
https://blog.csdn.net/qq_38737428/article/details/117373835?spm=1001.2014.3001.5501
但是这段代码leetcode上通过不了。超时了。。。。
害,一般暴力异或的情况都会超时。。。。。

法二:

思路分析: 我们将数组中的数变成二进制列出来,如图。在这里插入图片描述

只看第一位的情况下:
从左往右看,取每个二进制的第一位数,即 :
4的二进制的第一位数0。
14的二进制的第一位数1.
2的二进制的第一位数0。
按照汉明距离的定义。
4和14的汉明距离为1。
4和2的汉明距离为1.
14和2汉明距离为0。 汉明距离总和:2
只看第二位的情况下:
4的二进制的第二位数1。
14的二进制的第二位数1.
2的二进制的第二位数0。
按照汉明距离的定义。
4和14的汉明距离为0。
4和2的汉明距离为1。
14和2汉明距离为1。 汉明距离总和:2

通过上面两个例子,其实不难发现,每一列的汉明距离总和为‘1’的个数乘以‘0’的个数。

这样我们只需要吧每一列的汉明距离加起来就行了。
核心算法代码:

for i in range(ln):  # 遍历全部的列
    zero = 0  #  每一列统计完了 计数器归零
    one = 0
    for j in range(len(nums)):
        if list[j][i] == '0':
            zero += 1
        else:
            one +=1
    res += zero * one
print(res)

由于列表中的数转换成二进制可能位数不一样,所以需要统一位数,在位数短的前面补0。
比如:
1二进制为1
2二进制为10。
所以。。。
吧 1 前面补0 变为01 这样就可以和下面的10有相同位数了。方便使用上面的算法。

max_num = max(nums)  # 找列表中最大的数
ln = len(bin(max_num)) # 把最大的数变为二进制并记录他的长度

我们用前面拿到的最长字符串长度,给短位的补0。
我们可以使用format函数进行进制转换和位数控制。给定的列表中最大的数字其转换为二进制之后一定是长度最长的。

for i in nums:
    i = '{:0{}b}'.format(i,ln)
    list.append(i)

PS:
8位二进制
‘{:08b}’.format(9)
‘00001001’
上面的b换成o就是换成八进制,换成x就是十六进制。

完整代码:

nums = [4, 14, 2]
res = 0
max_num = max(nums)
ln = len(bin(max_num))
list = []
for i in nums:
    i = '{:0{}b}'.format(i,ln)
    list.append(i)
print(list)
for i in range(ln):
    zero = 0
    one = 0
    for j in range(len(nums)):
        if list[j][i] == '0':
            zero += 1
        else:
            one +=1
    res += zero * one
print(res)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深度不学习!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值