题目描述
给定一个包含从 1 到 n+2 的整数的数组,其中恰好有两个数字缺失。请找出这两个缺失的数字。
输入是一个整数数组 nums,长度为 n。输出是缺失的两个整数。
解题思路
这道题可以看作是「丢失的数字」与「只出现一次的数字 III」的结合体。
核心思想是利用异或(XOR)运算的性质:
- 任何数与自身异或结果为 0。
- 任何数与 0 异或结果为其本身。
- 异或运算满足交换律和结合律。
如果我们把数组中的所有元素与区间 [1, n+2] 内的所有数字进行异或,那么出现两次的数字会相互抵消,最终剩下的结果就是两个缺失数字的异或值(记为 a ^ b)。由于 a 不等于 b,它们的异或结果中至少有一位是 1。我们可以找到这个差异位,根据该位将数字分为两组,分别进行异或,即可分离出 a 和 b。
代码实现
方法一:提取最右侧的 1
这种方法直接利用补码特性快速定位差异位,效率较高。
class Solution {
public:
vector<int> missingTwo(vector<int>& nums) {
int temp = 0;
// 1. 异或数组中的所有元素
for (auto& x : nums) temp ^= x;
// 2. 异或区间 [1, n+2] 的所有数字
for (int i = 1; i <= nums.size() + 2; i++) temp ^= i;
// 此时 temp 为 a ^ b,必然至少有一位是 1
// 提取最右侧的 1,例如 temp=...100,ls=...001
int ls = temp & (-temp);
int a = 0, b = 0;
// 3. 根据差异位分组异或
for (auto& x : nums) {
if (x & ls) a ^= x;
else b ^= x;
}
for (int i = ; i <= nums.() + ; i++) {
(i & ls) a ^= i;
b ^= i;
}
{a, b};
}
};


