算法1
(异或运算) $O(n)$
当一个值与另一个值同时异或运算两次后,还是等于原来的值。
1. 首先遍历整个数组,对整个数组的每个值求异或。
2. 得到的结果是只出现一次的两个数的异或结果,因为这两个值是不相同的,所以异或的结果不可能为零,所以一定有一位是1,也就是一定有一位这两个值不相同。
3. 那么按这一位,将整个数组分成两部分,然后对两个数组分别进行异或遍历,就可以得到只出现一次的两个值
本题难点在于找到两个数不同的那一位
将遍历的到的最后的值,和1进行&运算,如果==1,此时最低位为1,如果为0,则向右移动,每向右移动一位,就将最后用来分组的值乘以2即可。
然后遍历整个数组的时候,如果与分组的值&的结果为0,是一组进行异或,反之亦然。
Java 代码
class Solution {
public int[] findNumsAppearOnce(int[] nums) {
if(nums==null||nums.length<2)
return null;
int res = 0;
int len = nums.length;
for(int i = 0;i<len;i++){
res^=nums[i];
}
int index = findFirstBit1(res);
int num1=0 ,num2=0;
for(int i= 0; i < len ;i++){
if((nums[i]&index)==0)
num1^=nums[i];
else
num2^=nums[i];
}
return new int[]{num1,num2};
}
public static int findFirstBit1(int num){
if(num<0)
return -1;
int indexOf1 = 1;
while (num!=0){
if((num&1)==1)
return indexOf1;
else{
num = num>>1;
indexOf1*=2;
}
}
return -1;
}
}