题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
题目提示:num1,num2分别为长度为1的数组。传出参数;将num1[0],num2[0]设置为返回结果

3.第三次做 题目变形 依然位运算

题目二:数组中唯一只出现一次的数字
在一个数组中除一个数组只出现一次之外,其他数字都出现了三次,
请找出那个只出现一次的数字。

思路:之前的思路不能解决这个问题,因为三个相同的数组异或结果还是该数字。还是沿用位运算的思路:如果一个数字出现三次,它的二进制表示的每一位(0或1)也出现三次。每一位的和都能被3整除。我们把数组中所有数字的二进制表示的每一位都加起来。如果某一位的和能被3整除,那么那个只出现一次的数字二进制表示中对应的那一位是0,否则就是1。

public static int FindNumberAppreaingOnce(int [] array) {
        if(array == null)    return 0;
        int[] bitMask = new int[32];
        int i, j, res = 0;
        for(i = 0; i<array.length; i++){
            for(j = 31; j>=0; j--){
                bitMask[j] += array[i]&1;
                array[i] = array[i]>>1;
            }
        }
        for(j = 0; j<32; j++){
            res = (res<<1) + bitMask[j]%3;

        }
        System.out.println(res);
        return res;
    }

2.第二次做:位运算 异或思路

看了讨论和题解,果然不是哈希这么简单。思路的核心是:两个相同数字异或=0,一个数和0异或还是它本身。沿着这个思路,关键问题是如何将数组分成两个部分,每一部分只包含一个解。这样每部分异或下来得到的就是一个解。讲数组分成两部分的方案:
根据异或的结果1所在的最低位:
我们首先还是先异或,剩下的数字肯定是A、B异或的结果,这个结果的二进制中的1,表现的是A和B的不同的位。我们就取第一个1所在的位数,假设是第3位,接着把原数组分成两组,分组标准是第3位是否为1。如此,相同的数肯定在一个组,因为相同数字所有位都相同,而不同的数,肯定不在一组。

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        int res = 0, count = 0, i;
        for(i = 0; i<array.length; i++){
            res ^= array[i];
        }
        //取第一个为1的位数作为分组标准
        while((res&1)==0){
            res = res>>1;
            count++;
        }
        for(i = 0; i<array.length; i++){
            if((array[i]&(1<<count))==0){
                num1[0] = num1[0]^array[i];
            }
            else{
                num2[0] = num2[0]^array[i];
            }
        }
    }
}

知识库中丰富的Tips:
1. 取数的某一特定二进制位的值——(右移特定位&1)
2. 判断某数特定二进制位的值————(1左移特定位&该数 判断是否为0)

1.第一次做:hash用空间换时间

public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        int[] hasharray = new int[10000000];
        for(int i=0; i<array.length; i++){
            hasharray[array[i]]++;
        }
        int count=0;
        for(int i=0; i<hasharray.length; i++){
            if(hasharray[i]==1 && count==0){
                num1[0]=i;
                count++;
            }
            if(hasharray[i]==1 && count==1)
                num2[0]=i;
        }
    }
}