劍指offer之陣列中數字出現的次數
阿新 • • 發佈:2018-11-12
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;
}
}