Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
For example:
Given nums = [1, 2, 1, 3, 2, 5], return [3, 5].
Note: The order of the result is not important. So in the above example, [5, 3] is also correct. Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?
//O(N^2) time (SLOW!!!)
#include<iostream>#include<vector>usingnamespace std;booldoesElementExist(vector<int>& nums,int elem) {for (int i =0; i <nums.size(); i++)if (nums.at(i) == elem) returntrue;returnfalse;}vector<int> singleNumber(vector<int>& nums) { vector<int> temp;int i =0;temp.push_back(nums.at(i));for (i =1; i <nums.size(); i++) {if (!doesElementExist(temp,nums.at(i))) temp.push_back(nums.at(i)); }return temp;}intmain(){ vector<int> nums2 = { 1,2,3,4,5,6,7,8,9,0,0 }; vector<int> singled =singleNumber(nums2);for (auto i : singled) cout << i <<' ';}
//O(NlogN) + O(N) [faster, but still not fast enough]
#include<iostream>#include<vector>#include<algorithm>usingnamespace std;vector<int> singleNumber(vector<int>& nums) {sort(nums.begin(),nums.end());int first =0, second =1;int fixedFirst =0, fixedSecond =1;int counterToErase =1;bool unique =true;while (fixedSecond <nums.size()) { // check if two or more of the same numberswhile (nums.at(first) ==nums.at(second)) { counterToErase++; second++; unique =false;if (second >=nums.size()) break; } // there were duplicatesif (!unique) { // erase the amount countednums.erase(nums.begin() + fixedFirst,nums.begin() + counterToErase + fixedFirst); counterToErase =1; first = fixedFirst; second = fixedSecond; unique =true; } // there were no duplicateselse { first = fixedFirst +=2; second = fixedSecond +=2; } //for (auto i : nums) cout << i << ' '; cout << endl; }return nums;}intmain(){ vector<int> nums2 = { 1,1,2,3,4,5,6,7,8,9,0,0,1,2,1,2,2,1,1,2,3,4,1,2,1,2,3,1,12,3,1231,1,31 }; vector<int> singled =singleNumber(nums2);for (auto i : singled) cout << i <<' ';}
//O(N), O(1) space
Here I know that if I first xor all the elements, the return will be the two unique xor'd elements. x ^ y = (2 unique elements xor'd).
If I can find one of the unique elements, I can find the other, since (2 unique elements xor'd) ^ x = y, as the inverse of xor = xor.
So we've reduced the problem into just finding any one of the first single numbers.
Doing this isnt really intuitive, we apparently have the first find the first set bit of cum that ill call temp. Then we xor anything in the number of sequence again that is >= temp, inverse of temp, or is zero. This alone will return the first unique element.
vector<int> singleNumber(vector<int>& nums) { vector<int>singlenum (2);int cum =0;for (auto i : nums) { cum ^= i; } // get first set bitint temp = cum &-cum;for (auto i : nums) {if ((i & temp) ==0)singlenum[0] ^= i; } // x ^ y = cum, inverse of xor = xorsinglenum[1] =singlenum[0] ^ cum;return singlenum;}