40.数组中只出现一次的数字

题目描述

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

题目解答

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        if(array==null || array.length<2){
            return;
        }
        //所有array异或后的结果
        int temp=0;
        for(int i=0;i<array.length;i++){
            temp^=array[i];
        }
        
        int indexOf1=findFirstBitIs(temp);
        
        //通过第i位是不是1,将array分为两个数组,这两个数组分别异或,出现两次的抵消为0,剩下的就是只出现一次的数字
        for(int i=0;i<array.length;i++){
            if(isBit(array[i],indexOf1)){
                num1[0]^=array[i];
            }else{
                num2[0]^=array[i];
            }
        }
    }
    
    //在整数num的二进制表示中找到最右边是1的位
    private int findFirstBitIs(int num){
        int indexBit=0;
        while(((num&1)==0) && (indexBit)<8*4){
            num=num>>1;
            ++indexBit;
        }
        return indexBit;
    }
    
    //判断在num的二进制表示中从右边数起的indexBit位是不是1
    private boolean isBit(int num,int indexBit){
        num=num>>indexBit;
        return (num&1)==1;
    }
}

 

简单版本:一个数组里除了一个数字之外,其他的数字都出现了两次。请写程序找出这个只出现一次的数字。

异或运算的性质:任何一个数字异或它自己都等于0 。

我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字,因为那些出现两次的数字全部在异或中抵消掉了。

 

针对本题:从头到尾依次异或数组中的每一个数字,最终得到的结果就是两个只出现一次的数字的异或结果。

这两个数字不一样,异或结果不为0 ,它的二进制表示中至少就有一位为1 。

在结果中找到第一个为1 的位置,记为第N 位。

现在我们以第N 位是不是1 为标准,把原数组中的数字分成两个子数组,第一个子数组中每个数字的第N 位都为1 ,而第二个子数组的每个数字的第N 位都为0 。

posted @ 2019-01-09 10:06  chan_ai_chao  阅读(180)  评论(0编辑  收藏  举报