# 260. 只出现一次的数字 III (Medium)

## 问题描述

[260. 只出现一次的数字 III][link] (Medium)

[link]: https://leetcode.cn/problems/single-number-iii/

给你一个整数数组 `nums`，其中恰好有两个元素只出现一次，其余所有元素均出现两次。 找出只出现一次的那两
个元素。你可以按 **任意顺序** 返回答案。

你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。

**示例 1：**

```
输入：nums = [1,2,1,3,2,5]
输出：[3,5]
解释：[5, 3] 也是有效的答案。
```

**示例 2：**

```
输入：nums = [-1,0]
输出：[-1,0]
```

**示例 3：**

```
输入：nums = [0,1]
输出：[1,0]
```

**提示：**

- `2 <= nums.length <= 3 * 10⁴`
- `-2³¹ <= nums[i] <= 2³¹ - 1`
- 除两个只出现一次的整数外， `nums` 中的其他数字都出现两次

## 解题思路

首先对所有数取异或，假设要找出来的元素分别为 $a$ 和 $b$，那么异或的结果就是 $c = a \oplus b$，我们考虑求 $c$ 的 lowbit，即 $c \& (-c)$，那么我们就可以把所有元素分成两类，一类是 $nums[i] \& lowbit = 0$，另一类是不为 $0$，$a$ 和 $b$ 一定是各属于一类，如果第一类元素的所有值的异或就是 $a$，那么第二类所有元素的异或值就是 $b$。

## 代码

```cpp
class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
       	long res = 0;
       	int n = nums.size();
       	for (int i = 0; i < n; ++i) {
       		res = res ^ nums[i];
       	} 
       	// 找出 res 的第一个 1
       	long c = (res & (-res));
       	int res1 = 0, res2 = 0;
       	for (int i = 0; i < n; ++i) {
       		if (nums[i] & c) {
       			res1 = res1 ^ nums[i];
       		} else {
       			res2 = res2 ^ nums[i];
       		}
       	}
       	return {res1, res2};
    }
};
```



