解题思路
位运算
异或运算:两个相同的数异或为0
1. 所有数异或一遍,剩下的就是两个不相同的数的异或值 x ^ y
2. x 和 y 肯定在某一位(第k位)上一个为0,一个为1
3. 找出所有第k位为1的数,剩下的就是所有第k位为0的数
4. 分别对这两个集合做异或运算,集合一就剩下x,集合二就剩y。
5. 返回x和y
class Solution {
public:
vector<int> findNumsAppearOnce(vector<int>& nums) {
int sum = 0;
for(auto x : nums) sum ^= x; // 将所有数都异或一遍 sum = x ^ y。想同的数异或为0
int k = 0;
while(!(sum >> k & 1)) k ++; // 找出 x 和 y 在第 k 位不同(此处是求第k位为1的)
int first = 0;
for(auto x : nums)
if(x >> k & 1) // 求出所有第k位为1的数
first ^= x; // 运算完后first就是两个不同的数之一
return vector<int>({first, sum ^ first});
}
};
hash表
时间复杂度 O(n)
hash表的存取是O(1),遍历了两遍数组为2n,所以时间复杂度为O(n);
class Solution {
public:
vector<int> findNumsAppearOnce(vector<int>& nums) {
vector<int> ans;
unordered_map<int, int> hash;
for(int i = 0; i < nums.size(); i ++){
hash[nums[i]]++;
}
for(auto x : nums){
if(hash[x] == 1) ans.push_back(x);
}
return ans;
}
};