两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量。
计算一个数组中,任意两个数之间汉明距离的总和。
示例:
输入: 4, 14, 2
输出: 6
解释: 在二进制表示中,4表示为0100,14表示为1110,2表示为0010。(这样表示是为了体现后四位之间关系)
所以答案为:
HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6.
注意:
数组中元素的范围为从 0到 10^9。
数组的长度不超过 10^4。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/total-hamming-distance
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
第一种思路:
暴力解,
两个数一组计算汉明距离,再累加在一起。
时间复杂度:O(N^2 * log(K)), K = log2(10 ^9)
空间复杂度:O(1)
第二种思路:
采取位运算的思想来计算答案,
比如对于样例输入= [4, 14, 2],
4 = 0100, 14 = 1110, 2 = 0010,
所以从右往左的:
第0位,有三个零,汉明距离为0
第1位,有两个一,一个零,2 * 1 = 2
第2位,有两个一,一个零,2 * 1 = 2
第3位,有一个一,两个零,2 * 1 = 2
最后累加在一起就是2 + 2 + 2 = 6。
算法本质就是找到每一位上,输入数组中二进制形式在这一位上的为1 的数的个数, 乘上 为0的数的个数,
最后累加在一起,即是答案。
时间复杂度:O(Nlog(K)),
空间复杂度:O(K)。
class Solution(object):
def totalHammingDistance(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
max_l = len(bin(max(nums))[2:])
dic = dict()
for i in range(max_l + 1):
dic[i] = [0, 0] # [0的个数,1的个数]
for num in nums:
s = bin(num)[2:]
if len(s) < max_l: # 如果长度不够则需要补全
s = (max_l - len(s)) * "0"+ s
for i, digit in enumerate(s):
dic[i][int(digit)] += 1
res = 0
for key, val in dic.items():
cnt0, cnt1 = val[0], val[1]
res += cnt0 * cnt1
return res
第三种思路:
第二种思路的进阶版,其实没必要用哈希表存结果,
每一位算完了直接累加。
class Solution(object):
def totalHammingDistance(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
res = 0
mask = 1
for i in range(32):
cnt_one = 0
for num in nums:
cnt_one += 1 if num & mask else 0
res += cnt_one * (len(nums) - cnt_one)
mask = mask << 1
return res