题目描述:
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。你可以假设这两个数字一定存在。
样例
输入:[1,2,3,3,4,4]
输出:[1,2]
分析:
方法一:
采用哈希表,时间和空间复杂度均为O(n)。
class Solution {
public:
vector<int> findNumsAppearOnce(vector<int>& nums) {
unordered_map<int,int> m;
vector<int> ans;
for(auto x : nums) m[x]++;
for(auto x : nums){
if(m[x] == 1) ans.push_back(x);
}
return ans;
}
};
方法二:
我们知道,如果一个数组中只有一个数字出现了一次,其他数字都出现两次的话,将这个数组所有的数异或起来就得到了这个数。本题我们也将所有数异或起来得到sum,设所求的两个只出现一次的数分别为a和b,则sum = a ^ b。现在我们想办法将a和b分开,sum中必然有一位等于1,否则a = b,假设是自右向左第k位等于1,那么a和b的第k位必然一个为0一个为1.我们再次遍历数组,将第k位都为1的数异或起来得到l,则l就是所求的a。另一个数b不用再次异或多个数,只用将a异或sum即可得到b。比如 10010 ^ 01110 = 11100,有10010 ^ 11100 = 01110。
这种方法时间复杂度为O(n),不需要额外的辅助空间。
class Solution {
public:
vector<int> findNumsAppearOnce(vector<int>& nums) {
int sum = 0,l = 0;
for(auto x : nums) sum ^= x;
int k = 0;
while(!(sum >> k & 1)) k++;
for(auto x : nums){
if(x >> k & 1) l ^= x;
}
return vector<int>{l,l ^ sum};
}
};