给你一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序  返回答案。
你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。
示例 1: 
**输入:** nums = [1,2,1,3,2,5]
**输出:** [3,5]
**解释:** [5, 3] 也是有效的答案。
 
示例 2: 
**输入:** nums = [-1,0]
**输出:** [-1,0]
 
示例 3: 
**输入:** nums = [0,1]
**输出:** [1,0]
 
提示: 
2 <= nums.length <= 3 * 104 
-231 <= nums[i] <= 231 - 1 
除两个只出现一次的整数外,nums 中的其他数字都出现两次 
 
📺 视频题解 
📖 文字题解 方法一:哈希表 思路与算法 
我们可以使用一个哈希映射统计数组中每一个元素出现的次数。
在统计完成后,我们对哈希映射进行遍历,将所有只出现了一次的数放入答案中。
代码 
[sol1-C++] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class  Solution  {public :    vector<int > singleNumber (vector<int >& nums)   {         unordered_map<int , int > freq;         for  (int  num: nums) {             ++freq[num];         }         vector<int > ans;         for  (const  auto & [num, occ]: freq) {             if  (occ == 1 ) {                 ans.push_back (num);             }         }         return  ans;     } }; 
 
[sol1-Java] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class  Solution  {    public  int [] singleNumber(int [] nums) {         Map<Integer, Integer> freq = new  HashMap <Integer, Integer>();         for  (int  num : nums) {             freq.put(num, freq.getOrDefault(num, 0 ) + 1 );         }         int [] ans = new  int [2 ];         int  index  =  0 ;         for  (Map.Entry<Integer, Integer> entry : freq.entrySet()) {             if  (entry.getValue() == 1 ) {                 ans[index++] = entry.getKey();             }         }         return  ans;     } } 
 
[sol1-C#] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public  class  Solution  {    public  int [] SingleNumber (int [] nums )  {         Dictionary<int , int > freq = new  Dictionary<int , int >();         foreach  (int  num in  nums) {             if  (freq.ContainsKey(num)) {                 ++freq[num];             } else  {                 freq.Add(num, 1 );             }         }         int [] ans = new  int [2 ];         int  index = 0 ;         foreach  (KeyValuePair<int , int > pair in  freq) {             if  (pair.Value == 1 ) {                 ans[index++] = pair.Key;             }         }         return  ans;     } } 
 
[sol1-Python3] 1 2 3 4 class  Solution :    def  singleNumber (self, nums: List [int ] ) -> List [int ]:         freq = Counter(nums)         return  [num for  num, occ in  freq.items() if  occ == 1 ] 
 
[sol1-JavaScript] 1 2 3 4 5 6 7 8 9 10 11 12 13 var  singleNumber = function (nums ) {    const  freq = new  Map ();     for  (const  num of  nums) {         freq.set (num, (freq.get (num) || 0 ) + 1 );     }     const  ans = [];     for  (const  [num, occ] of  freq.entries ()) {         if  (occ === 1 ) {             ans.push (num);         }     }     return  ans; }; 
 
[sol1-TypeScript] 1 2 3 4 5 6 7 8 9 10 11 12 13 function  singleNumber (nums: number [] ): number [] {    const  freq = new  Map ();     for  (const  num of  nums) {         freq.set (num, (freq.get (num) || 0 ) + 1 );     }     const  ans : number [] = [];     for  (const  [num, occ] of  freq.entries ()) {         if  (occ === 1 ) {             ans.push (num);         }     }     return  ans; }; 
 
[sol1-Golang] 1 2 3 4 5 6 7 8 9 10 11 12 func  singleNumber (nums []int )   (ans []int ) {    freq := map [int ]int {}     for  _, num := range  nums {         freq[num]++     }     for  num, occ := range  freq {         if  occ == 1  {             ans = append (ans, num)         }     }     return  } 
 
复杂度分析 
方法二:位运算 思路与算法 
在理解如何使用位运算解决本题前,读者需要首先掌握「136. 只出现一次的数字」  中的位运算做法。
假设数组 $\textit{nums}$ 中只出现一次的元素分别是 $x_1$ 和 $x_2$。如果把 $\textit{nums}$ 中的所有元素全部异或起来,得到结果 $x$,那么一定有:
$$ x = x_1 \oplus x_2 $$
其中 $\oplus$ 表示异或运算。这是因为 $\textit{nums}$ 中出现两次的元素都会因为异或运算的性质 $a \oplus b \oplus b = a$ 抵消掉,那么最终的结果就只剩下 $x_1$ 和 $x_2$ 的异或和。
$x$ 显然不会等于 $0$,因为如果 $x=0$,那么说明 $x_1 = x_2$,这样 $x_1$ 和 $x_2$ 就不是只出现一次的数字了。因此,我们可以使用位运算 $\texttt{x & -x}$ 取出 $x$ 的二进制表示中最低位那个 $1$,设其为第 $l$ 位,那么 $x_1$ 和 $x_2$ 中的某一个数的二进制表示的第 $l$ 位为 $0$,另一个数的二进制表示的第 $l$ 位为 $1$。在这种情况下,$x_1 \oplus x_2$ 的二进制表示的第 $l$ 位才能为 $1$。
这样一来,我们就可以把 $\textit{nums}$ 中的所有元素分成两类,其中一类包含所有二进制表示的第 $l$ 位为 $0$ 的数,另一类包含所有二进制表示的第 $l$ 位为 $1$ 的数。可以发现:
因此,如果我们将每一类的元素全部异或起来,那么其中一类会得到 $x_1$,另一类会得到 $x_2$。这样我们就找出了这两个只出现一次的元素。
代码 
[sol2-C++] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class  Solution  {public :    vector<int > singleNumber (vector<int >& nums)   {         int  xorsum = 0 ;         for  (int  num: nums) {             xorsum ^= num;         }                  int  lsb = (xorsum == INT_MIN ? xorsum : xorsum & (-xorsum));         int  type1 = 0 , type2 = 0 ;         for  (int  num: nums) {             if  (num & lsb) {                 type1 ^= num;             }             else  {                 type2 ^= num;             }         }         return  {type1, type2};     } }; 
 
[sol2-Java] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class  Solution  {    public  int [] singleNumber(int [] nums) {         int  xorsum  =  0 ;         for  (int  num : nums) {             xorsum ^= num;         }                  int  lsb  =  (xorsum == Integer.MIN_VALUE ? xorsum : xorsum & (-xorsum));         int  type1  =  0 , type2 = 0 ;         for  (int  num : nums) {             if  ((num & lsb) != 0 ) {                 type1 ^= num;             } else  {                 type2 ^= num;             }         }         return  new  int []{type1, type2};     } } 
 
[sol2-C#] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public  class  Solution  {    public  int [] SingleNumber (int [] nums )  {         int  xorsum = 0 ;         foreach  (int  num in  nums) {             xorsum ^= num;         }                  int  lsb = (xorsum == int .MinValue ? xorsum : xorsum & (-xorsum));         int  type1 = 0 , type2 = 0 ;         foreach  (int  num in  nums) {             if  ((num & lsb) != 0 ) {                 type1 ^= num;             } else  {                 type2 ^= num;             }         }         return  new  int []{type1, type2};     } } 
 
[sol2-Python3] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class  Solution :    def  singleNumber (self, nums: List [int ] ) -> List [int ]:         xorsum = 0          for  num in  nums:             xorsum ^= num                  lsb = xorsum & (-xorsum)         type1 = type2 = 0          for  num in  nums:             if  num & lsb:                 type1 ^= num             else :                 type2 ^= num                  return  [type1, type2] 
 
[sol2-JavaScript] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var  singleNumber = function (nums ) {    let  xorsum = 0 ;          for  (const  num of  nums) {         xorsum ^= num;     }     let  type1 = 0 , type2 = 0 ;     const  lsb = xorsum & (-xorsum);     for  (const  num of  nums) {         if  (num & lsb) {             type1 ^= num;         } else  {             type2 ^= num;         }     }     return  [type1, type2]; }; 
 
[sol2-Golang] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 func  singleNumber (nums []int )   []int  {    xorSum := 0      for  _, num := range  nums {         xorSum ^= num     }     lsb := xorSum & -xorSum     type1, type2 := 0 , 0      for  _, num := range  nums {         if  num&lsb > 0  {             type1 ^= num         } else  {             type2 ^= num         }     }     return  []int {type1, type2} } 
 
[sol2-C] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 int * singleNumber (int * nums, int  numsSize, int * returnSize)  {    int  xorsum = 0 ;     for  (int  i = 0 ; i < numsSize; i++) {         xorsum ^= nums[i];     }          int  lsb = (xorsum == INT_MIN ? xorsum : xorsum & (-xorsum));     int  type1 = 0 , type2 = 0 ;     for  (int  i = 0 ; i < numsSize; i++) {         int  num = nums[i];         if  (num & lsb) {             type1 ^= num;         } else  {             type2 ^= num;         }     }     int  *ans = (int  *)malloc (sizeof (int ) * 2 );     ans[0 ] = type1;     ans[1 ] = type2;     *returnSize = 2 ;     return  ans; } 
 
复杂度分析