方法:异或运算

根据异或运算的性质,如果一个数组只有出现一次的数字,那么数组中所有的数字通过异或运算最终的结果就是该数字。

如果数组中有两个只出现一次的数字(target1、target2),我们首先就需要将targer1和target2区分开来。数组全部进行异或运算后最终的结果为target1 ^ target2,通过这个结果我们可以反推出target1和target2在哪些位上是不一致的,这样就可以将数组分为两类,分别进行异或运算得到target1和target2。

时间复杂度:o(n)。需要遍历数组

空间复杂度:o(1)。无额外辅助空间。

class Solution {
  public:
    vector<int> FindNumsAppearOnce(vector<int>& nums) {
        vector<int> res;
        int k = 1;
        int temp = 0;
        int res1 = 0;
        int res2 = 0;

        for (int i = 0; i < nums.size(); i++) {
            temp = temp ^ nums[i];
        }
		//找到两个数不相同的第一位
        while ((k & temp) == 0) {
            k <<= 1;
        }

        for (int i = 0; i < nums.size(); i++) {
		  	//分两类进行异或运算
            if (nums[i] & k)
                res1 = res1 ^ nums[i];
            else
                res2 = res2 ^ nums[i];
        }
		//按升序排列
        if (res1 > res2) {
            res.push_back(res2);
            res.push_back(res1);
        } else {
            res.push_back(res1);
            res.push_back(res2);
        }

        return res;
    }
};

此题也可通过哈希简单求解,但需要额外的辅助空间。