剑指offer-数组中只出现一次的数字

题目描述

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

时间复杂度O(N),空间复杂度O(1)

思路

剑指offer思路.

首先将数组中的数组做异或和,这个结果是两个数字的异或和.

然后找到这个异或和的最低位的1的位置,记为pos(这个异或和必定不为0,一定存在至少一个1)

然后再遍历数组,对每一位数字,如果它的第pos位为1,那么就用res1做异或和,反之用res2做异或和.

因为对于两个只出现一次的数字,他们在pos位一定不相同.那么就会分别分配到res1,res2

而对于那些出现两次的数字,无论他们的pos位如何,一定会在同一个res做两次异或.

最后,res1和res2就是两个只出现一次的数字.

code

public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
    int sum = 0;
    int len = array.length;
    for (int i = 0; i < len; i++) {
        sum ^= array[i];
    }
    int tmps = sum;
    int cnt = 0;
    while((tmps & 1) != 1) {
        tmps >>>= 1;
        cnt++;
    }

    int res1=0,res2=0;
    for (int i = 0; i < len; i++) {
        if(yi(array[i],cnt) == 1) {
            res1 ^= array[i];
        } else {
            res2 ^= array[i];
        }
    }
    num1[0] = res1;
    num2[0] = res2;
}

public int yi(int n,int cnt) {
    n >>>= cnt;
    return n & 1;
}