要求必须是O(1)空间复杂度,那么必然不能使用哈希表或者桶这样的集合:
只能考虑用位运算解决:
看代码之前我们一定要明白异或运算的几个性质:a^ b ^ c = a ^ c ^b,a ^ b=b ^ a,即满足交换律和结合律,a ^ a=0,a ^ 0=a;
那么数组中所有元素异或的结果就是那两个只出现了一次的数异或的结果,接着只需要考虑将这个两个数分开即可:
那么我们需要明白的是这个结果产生的二进制数是异或的结果,就意味着从右往左数结果rec出现的第一个1就代表了两个数从右往左在这个位置不一样,一个为0,一个为1,用while((rec&mask)==0){ mask<<=1; }找到这个位置mask。
那么在回到数组每一个数去跟mask相&,分成两组数,那么两个需要的数分别在两个数组中,因为你他们在mask位置,一个为1,一个为0,而mask除了这个位置为1,其余全为0,每组数都去异或一下就得到了两个要求的数,记住a ^ a=0,
class Solution {
public int[] singleNumbers(int[] nums) {
int idx=0;
int rec=0;
for(int num:nums){
rec^=num;
}
int mask=1;
while((rec&mask)==0){
mask<<=1;
}
int a=0,b=0;
for(int nu:nums){
if((nu&mask)==0)a^=nu;
else b^=nu;
}
return new int[]{a,b};
}
}