两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量。
计算一个数组中,任意两个数之间汉明距离的总和。
示例:
输入: 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!)
这么多次
华丽丽地超时了
int totalHammingDistance(int* nums, int numsSize)
{
int sum = 0;
int tmp;
int i, j;
for (i = 0; i < numsSize - 1; i++) {
for (j = i + 1; j < numsSize; j++) {
/* count Hamming Distance of each pair */
tmp = nums[i] ^ nums[j];
while (tmp) {
sum += 1;
tmp &= tmp - 1;
}
}
}
return sum;
}
折叠法(我乱命名的)
数组里面全部都是int类型的,也就是32个比特,可以一个比特一个比特地进行比较
例如第一次比较全部数字的最后一个比特,算出最后一个比特的海明距离,再比较第二个比特的海明距离……
时间复杂度是O(n)
int totalHammingDistance(int* nums, int numsSize)
{
int sum = 0;
int cnt = 32;
int tmp = 0x1;
int zero, one;
int index;
while (cnt --) {
zero = one = 0;
for (index = 0; index < numsSize; index++) {
if (nums[index] & tmp) {
one += 1;
} else {
zero += 1;
}
}
sum += one * zero;
if (cnt > 1)
tmp <<= 1;
}
return sum;
}
主要是因为力扣里面不允许写自然溢出的算法,所以显得很别扭
impl Solution {
pub fn total_hamming_distance(nums: Vec<i32>) -> i32 {
let mut cnt = 0x1;
let mut sum = 0;
while cnt != 0 {
let mut zero = 0;
let mut one = 0;
for num in nums.iter() {
if num & (cnt >> 1) != 0 {
one += 1;
} else {
zero += 1;
}
}
sum += one * zero;
cnt <<= 1;
}
sum
}
}
正在学习Rust,就蛮写了一个Rust的算法
让人意外的是,Rust居然那么快