记录一下此题的操作思路,由于题目要求时间复杂度为O(n),空间复杂度为O(1),所以肯定是不能使用借助其他数据结构或者双指针遍历的方法了。这里使用的是位运算符。
主要是异或运算符,首先贴出异或运算符的几点重要性质。
1.如果我们对 0 和二进制位做 XOR 运算,得到的仍然是这个二进制位。
a⊕0=a
2.如果我们对相同的二进制位做 XOR 运算,返回的结果是 0。
a⊕a=0
3.XOR 满足交换律和结合律。
a⊕b⊕a=(a⊕a)⊕b=0⊕b=b
class Solution {
public:
vector<int> singleNumbers(vector<int>& nums) {
int res = 0;
int a = 0;
int b = 0;
for(int i =0;i<nums.size();i++)
res ^= nums[i];
int h =1;
while((res&h)==0)
h <<= 1;
for(int i =0;i<nums.size();i++){
if((h&nums[i])==0)
a ^= nums[i];
else
b ^= nums[i];
}
vector<int> num;
num.push_back(a);
num.push_back(b);
return num;
}
};
先使用res变量来记录所有数异或的结果,从异或结果上按位来看的话,有1的地方就是这两个变量产生的1(因为两个一样的数异或结果为0,异或又符合交换律)。所以这两个1必然是由这两个不同的数产生的,之后我们找到第一位不是0的位,用h变量记录下来。之后以这一位作为标志进行分组,与这一类&为1的分为一组,与这一类&为0的分为另一组。
分组的理由:因为这两个数是必然在不同的组内,然后相同的数必然在同一个组内。这之后在对两个组分别异或,就得到这两个数了。
需要注意的点:在c++中 == 运算符的优先级 大于 & 运算符的优先级,所以要用括号将 & 的两端给括起来,否则会导致结果出错。