1. 程式人生 > >劍指offer之陣列中數字出現的次數

劍指offer之陣列中數字出現的次數

1. 題目

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

2. 思路

首先,可以想一下,如果陣列中只有一個數字只出現了一次,其他數字都出現了兩次,怎麼找出這個數字呢?根據這個問題可以想到異或的一個性質:加任何一個數字異或它自己都等於0。也就是說,如果從頭到尾異或每個數字,那麼最終的結果就是那個只出現了一次的數字,因為那些成對出現的數字都在異或中抵消了。

根據上面的思路,我們異或陣列中的所有數字,這裡可以得到一個不為 0 的數字,這個數字是陣列中兩個只出現一次數字的異或結果。因為這個結果不為 0,因此我們可以從右向左找出這個數字二進位制第一個不為 0 的數字,根據這一位將陣列分為兩個子陣列(長度為 2),這一位為 1 的數字放在第一個子陣列中,這一位為 0 的數字放在第二個子陣列中。對這兩個子陣列進行異或操作,即可得到最終的結果。

3. 程式碼

public class F56FindNumsAppearOnce {
    public void solution(int[] data,int[] result){
	if(data==null || data.length<2)
	    return ;
	int resultExclusiveOR = 0;
	// 將陣列中所有數字都進行異或操作
	for(int i=0;i<data.length;i++)
	    resultExclusiveOR ^= data[i]; 
	// 找出異或操作結果二進位制第一個不為 0 的位置
	int indexOf1 =
findFirstBitsIs1(resultExclusiveOR); // 根據 indexOf1 位置上是否 1 分為兩個陣列 for(int i=0;i<data.length;i++){ if(isBit1(data[i],indexOf1)){ result[0] ^= data[i]; }else{ result[1] ^= data[i]; } } } private int findFirstBitsIs1(int num){ int index = 0 ; while((num&1)== 0){ num>>=
1; index++; } return index; } private boolean isBit1(int num,int index){ num >>= index; return (num&1)==1; } }