【Java】 劍指offer(56-1) 數組中只出現一次的兩個數字


 

本文參考自《劍指offer》一書,代碼采用Java語言。

更多:《劍指Offer》Java實現合集  

題目

  一個整型數組里除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。要求時間復雜度是O(n),空間復雜度是O(1)。

思路

  記住:兩個相同的數字異或等於0.

  如果數組中只有一個數字只出現一次,我們從頭到尾異或每個數字,那么最終的結果剛好是那個只出現一次的數字。

  而本題里數組中有兩個數字只出現一次,如果能夠將數組分為兩部分,兩部分中都只有一個數字只出現一次,那么就可以解決該問題了。

  求解方法:

  我們依舊從頭到尾異或每個數字,那么最終的結果就是這兩個只出現一次的數字的異或結果,由於兩個數不同,因此這個結果數字中一定有一位為1,把結果中第一個1的位置記為第n位。因為是兩個只出現一次的數字的異或結果,所以這兩個數字在第n位上的數字一定是1和0

   接下來我們根據數組中每個數字的第n位上的數字是否為1來進行分組,恰好能將數組分為兩個都只有一個數字只出現一次的數組,對兩個數組從頭到尾異或,就可以得到這兩個數了。

 

測試算例 

  1.功能測試(數組中有多對重復的數字;無重復的數字)

Java代碼

//題目:一個整型數組里除了兩個數字之外,其他的數字都出現了兩次。請寫程序
//找出這兩個只出現一次的數字。要求時間復雜度是O(n),空間復雜度是O(1)。

public class NumbersAppearOnce {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        if(array==null || array.length<2)
            return;
        int resultExclusiveOR=0;
        for(int i=0;i<array.length;i++)
            resultExclusiveOR^=array[i];
        
        int indexOf1=0;
        while(((resultExclusiveOR&1)==0) && (indexOf1<=4*8)){
        	resultExclusiveOR=resultExclusiveOR>>1;  //只有n>>1不完整,要n=n>>1
            indexOf1++;
        }
        
        num1[0]=0;
        num2[0]=0;
        for(int i=0;i<array.length;i++){
            if(((array[i]>>indexOf1)&1)==1)
                num1[0]^=array[i];
            else
                num2[0]^=array[i];
        }
    }
}

  

收獲

  1.當一個數字出現兩次(或者偶數次)時,用異或^ 可以進行消除。一定要牢記 異或的這個功能!

  2.將一組數字分為兩組,可以根據某位上是否為1來進行分組,即根據和1相與(&1)的結果來進行分組。

  3.判斷某個數x的第n位(如第3位)上是否為1,

    1)通過 x&00000100 的結果是否為0 來判斷。(不能根據是否等於1來判斷)

    2)通過(x>>3)&1 是否為0 來判斷

  4.將某個數x右移m位,一定要寫成 x=x>>m;而不能只寫成 x>>m;這個語句

  

更多:《劍指Offer》Java實現合集  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM