LeetCode/solutions/260. Single Number III.md
2020-02-13 22:05:32 +08:00

36 lines
2.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [260. Single Number III](https://leetcode.com/problems/single-number-iii/)
# 思路
这道题是之前 [136 Single Number](https://github.com/ShusenTang/LeetCode/blob/master/solutions/136.%20Single%20Number.md) 和[137 Single Number II](https://github.com/ShusenTang/LeetCode/blob/master/solutions/137.%20Single%20Number%20II.md)的再次拓展,依然是用位操作解决。
这题和136唯一不同就是此题有两个出现了一次的数, 所以我们按照136题类似的遍历一遍数组然后得到所有数字异或结果是待求两个数(设为res1和res2)的异或结果`res1^res2`, 所以我们不能直接这样做. 既然同时存在两个只出现过一次的数, 那么如果我们将数组分成两部分且这两部分数组分别包含了res1和res2, 然后再采用136完全一样的思路不就解决了吗。
所以**问题转换成如何将数组分成两个部分且这两部分分别包含res1和res2**. 还是利用位操作, 我们可以根据res1和res2不同的某一位来划分数组, 例如若二者第3位分别为0和1, 那么我们就根据"第三位为0还是为1"来划分数组. 我们不妨取二者不同位的最低(即最右)的那位, 即二者异或结果`res1^res2`最低位的1. 设`res=res1^res2`, 那么`res&(-res)`即res最低位的1。
总结一下这一类题:
| # | 要求 | 例题 | 基本思路 |
|---|---|---|---|
| 1 | 除一个数外,其他都出现两次 | [136. Single Number](https://leetcode.com/problems/single-number/) | 异或所有数 |
| 2 |除一个数外其他都出现kk > 1次 | [137. Single Number II](https://leetcode.com/problems/single-number-ii/) | 计算每一位1出现的次数模k |
| 3 |除两个数外,其他都出现两次 | [260. Single Number III](https://leetcode.com/problems/single-number-iii/) | 根据异或结果将数组分成两份转换为情况1求解 |
# C++
``` C++
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int res = 0, res1 = 0, res2 = 0;
for(auto num: nums) res ^= num;
int mask = res & (-res);
for(auto num: nums){
if(num & mask) res1 ^= num;
else res2 ^= num;
}
return vector<int>{res1, res2};
// return vector<int>{res1, res1 ^ res};
}
};
```