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

2.2 KiB
Raw Blame History

260. Single Number III

思路

这道题是之前 136 Single Number137 Single Number II的再次拓展,依然是用位操作解决。

这题和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 异或所有数
2 除一个数外其他都出现kk > 1 137. Single Number II 计算每一位1出现的次数模k
3 除两个数外,其他都出现两次 260. Single Number III 根据异或结果将数组分成两份转换为情况1求解

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};
    }
};