題目:
一個整形數組裏除了兩個數字意外,其他的數字都出現了兩次.請寫程序找出這兩個只出現一次的數字.
要求時間複雜度是On,空間複雜度爲O1
這個是上一篇 2016阿里巴巴java筆試題 的增強版...
還是使用異或,異或到了最後得到結果是怎麼樣的呢?
其餘的數字都互相異或變成了0,所以最後的結果就是這2個不相同的數字的異或結果.
就假定要找的兩個數字爲數字A和數字B
那麼怎麼分別得到這2個數字呢?
異或:1^1=0,1^0=1
就看最後異或的結果:他是一個二進制數,那麼出現1的地方肯定就是A與B的二進制不相同的地方.
那麼就異或的結果中,第一次出現1的時候就說明此時A與B中較大的那個當前位上爲1,較小的那個爲0.
根據這個,就把所有的數字分爲2組:當前位爲1的,當前位爲0的.
那麼原先的一組數據被分爲了2組,A,B又分別位於不同的組,那隻要分別異或就行了..
例子:
比如說1,1,2,2,3,4,5,5
最後異或的結果就是3^4=1110
根據倒數第4位上是否爲1,將原先的數組分爲2組:
1,1,2,2,3
4,5,5
這樣分別異或,第一組得到3,第二組得到4,完成
代碼:
public int[] find(int[] array) {
// 異或所有,得到總異或的結果
int result = array[0];
for (int i = 1; i < array.length; i++) {
result ^= array[i];
}
// 求出倒數第幾位爲第一個1
// 這裏count記錄的是倒數第幾-1
int count = -1;
while (result != 0) {
result = result >>> 1;
count++;
}
// 分爲兩種情況來異或
int target1 = 0;
int target2 = 0;
for (int i = 0; i < array.length; i++) {
if (((array[i] >>> count) & 1) == 1) {
target1 ^= array[i];
} else {
target2 ^= array[i];
}
}
return new int[] { target1, target2 };
}