leetcode477. 汉明距离总和
🤡过不了的暴力解:
class Solution {
public int totalHammingDistance(int[] nums) {
int n = nums.length,res = 0;
for(int i = 0;i < n;++i){
for(int j = i + 1;j < n;++j){
res += HammingDist(nums[i],nums[j]);
}
}
return res;
}
public int HammingDist(int x,int y){
int z = x ^ y,res = 0;
while(z > 0){
z &= (z - 1);++res;
}
return res;
}
}
法一:
在计算汉明距离时,我们考虑的是同一比特位上的值是否不同,而不同比特位之间是互不影响的。
对于数组 nums 中的某个元素 val,若其二进制的第 i 位为 1,我们只需统计 nums 中有多少元素的第 i 位为 0,即计算出了 val 与其他元素在第 i 位上的汉明距离之和。
具体地,若长度为 n 的数组 nums 的所有元素二进制的第 i 位共有 c 个 1,n−c 个 0,则些元素在二进制的第 i 位上的汉明距离之和为 c⋅(n−c)
我们可以从二进制的最低位到最高位,逐位统计汉明距离。将每一位上得到的汉明距离累加即为答案。具体实现时,对于整数 val 二进制的第 i 位,我们可以用代码 (val >> i) & 1 来取出其第 i 位的值。
此外,由于 10^9<2^30,我们可以直接从二进制的第 0 位枚举到第 29 位。
class Solution {
public int totalHammingDistance(int[] nums) {
int n = nums.length,res = 0;
for(int i = 0;i < 30;++i){
int countOne = 0;//统计本次右移之后末位为1的元素个数
for(int num : nums){
countOne += (num >> i) & 1;
}
res += countOne * (n - countOne);//本次右移末尾的汉明距离加到res
}
return res;
}
}