刷題 - 數組中只出現1次的兩個數

題目描述:

一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。

預備知識:

對於一個整數數組,首先我們先分析一個簡單的情況:假定數組中只有一個數據出現1次,其他數據都出現了兩次,如何找到這個只出現1次的數據?

位運算中,兩個數的異或運算規則是:二進制位相同返回0,不同返回1,由此兩個相同數據的異或值爲0,任何數據與0的異或還爲原值。如1100^1100=0000,1010^0000=1010。

所以可以很快想到,上面求唯一一個出現1次的數據就可以對數組中的數據全部異或,得到的結果就是隻出現1次的數據。

本題思路:

通過預備知識的內容,回到本題,本題的數組中由兩個只出現1次的數據,其餘數據都出現2次,設這兩個數據是A和B。

首先還是對數組中所有的數據進行異或處理,結果是A^B,我們分析一下這個結果:結果的二進制表示中,所有的0代表了A和B二進制相同的位,1代表了A和B二進制不同的位。

那麼我們就可以以A^B二進制結果中爲1的位對原數組進行劃分,例如A^B=0000100,倒數第3位爲1,遍歷原數組中所有的數據,其二進制表示中第3位爲0的劃分爲1組,第3位爲1的劃分到一組。

可以想到劃分後的這兩組,一定都是一堆出現2次的數據和1個出現1次的數據,由此就可以用預備知識中的處理方法得到結果了。

class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        if(data.size()<2)
            return ;
        int size=data.size();
        //數組中所有元素異或,結果爲兩個不同值的異或結果(同值異或結果爲0)
        int temp=data[0];
        for(int i=1;i<size;i++)
            temp=temp^data[i];
        if(temp==0)
            return ;
        //找到異或結果二進制表示中爲1的最低位,該位代表了原數組中不同的兩個值在此位不同
        int index=0;
        while((temp&1)==0){
            temp=temp>>1;
            ++index;
        }
        //以上面的index位的值將原數組劃分兩組,不同的值肯定被劃分到不同的組,同值元素肯定劃分到同組
        *num1=*num2=0;
        for(int i=0;i<size;i++){
            if(IsBit(data[i],index))
                *num1^=data[i];
            else
                *num2^=data[i];
        }
     }
    bool IsBit(int num,int index){
        num=num>>index;
        return (num&1);
    }
};

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章