将输入的 x 和 y 右移,逐位比较,统计对应二进制位不同的位置的数目,当 x | y 为 0 时,说明两个数最高位 1 统计完,结束循环。
代码实现
classSolution {
public:
inthammingDistance(int x, int y){
int ans = 0;
while (x | y) {
int a = x & 1, b = y & 1;
ans += a ^ b;
x >>= 1;
y >>= 1;
}
return ans;
}
};
这道题还可以用 lowbit 来求解,lowbit 可以提取一个数二进制表示最右侧的 1。
我们可以先将 x 和 y 异或起来,再统计异或结果中 1 的个数。
classSolution {
public:
intlowbit(int x){
return x & -x;
}
inthammingDistance(int x, int y){
int ret = 0;
for (int i = x ^ y; i > 0; i -= lowbit(i)) ret++;
return ret;
}
};
通过第 i 位上值的不同,将原数组划分,因为异或结果二进制表示位为 1 表示只出现一次的两个数字 a 和 b 该比特位的不同,我们只需要根据这个划分依据分别将对应的数字异或起来就能得到只出现一次的两个数字。
原理:异或运算,相同为 0,不同为 1。
代码实现
classSolution {
public:
vector<int> singleNumber(vector<int>& nums){
int x = 0; // a ^ b = xfor (auto e : nums) x ^= e;
// 判断 x 第几位是 1int i = 0;
for (i = 0; i < 32; ++i) if ((x >> i) & 1) break;
// 根据第 i 位划分原数组int a = 0, b = 0;
for (auto e : nums) {
if ((e >> i) & 1) a ^= e;
else b ^= e;
}
return {a, b};
}
};
classSolution {
public:
intsingleNumber(vector<int>& nums){
int x = 0;
for (int i = 0; i < 32; ++i) {
int bitSum = 0;
for (auto e : nums) bitSum += (e >> i) & 1;
x |= (bitSum % 3) << i;
}
return x;
}
};
classSolution {
public:
intmissingNumber(vector<int>& nums){
int x = 0;
for (auto e : nums) x ^= e;
for (int i = 0; i <= nums.size(); ++i) x ^= i;
return x;
}
};
高斯求和
classSolution {
public:
intmissingNumber(vector<int>& nums){
int n = nums.size();
// 高斯公式求和int sum = n * (n + 1) / 2;
for (auto e : nums) sum -= e;
return sum;
}
};
哈希
classSolution {
public:
intmissingNumber(vector<int>& nums){
int n = nums.size();
int* hash = newint[n + 1]{0};
for (auto e : nums) hash[e]++;
for (int i = 0; i <= n; ++i) {
if (hash[i] == 0) {
delete[] hash;
return i;
}
}
return-1;
}
};
异或结果二进制表示位为 1 表示缺失的两个数字 a 和 b 该比特位的不同,找出异或值二进制表示最低位的 1 是第 i 位。
通过第 i 位上值的不同,将 [1, n] 和数组 nums 的所有元素划分,我们只需要根据这个划分依据分别将对应的元素异或起来就能得到缺失的两个数字。
代码实现
classSolution {
public:
vector<int> missingTwo(vector<int>& nums){
// 1. 求出缺失两个数的异或 xint n = nums.size(), x = 0;
for (int i = 1; i <= n + 2; ++i) x ^= i;
for (auto e : nums) x ^= e;
// 2. 找出 a b 二进制中不同的那位 diffint diff = 0;
while (((x >> diff) & 1) == 0) diff++;
// 3. 根据 diff 位的不同,将所有的数划分为两类并异或int a = 0, b = 0;
for (auto e : nums) if ((e >> diff) & 1) a ^= e; else b ^= e;
for (int j = 1; j <= n + 2; ++j) if ((j >> diff) & 1) a ^= j; else b ^= j;
return {a, b};
}
};