1. 找出數組中只出現一次的數字
這個題目其實有兩種形式:
-
一個整型數組裏除了某一個數字之外,其他的數字都出現了兩次,找出這個只出現了一次的數字
如數組 [1,2,2,1,3], 則目標數字爲 3
-
一個整型數組裏除了某兩個數字之外,其他的數字都出現了兩次,找出這兩個只出現了一次的數字
如數組 [1,2,2,1,3,5], 則目標數字爲 3,5
2. 解法
2.1 只有一個不重複數字
思路:使用異或運算符^,0與其他數字異或的結果是那個數字,相等的數字異或得 0
- 數組中除了某一個數字只出現了一次之外,其他數字都出現了兩次,所以可定義一個變量賦初始值爲0,用這個變量與數組中每個數字做異或運算,並將這個變量值更新爲那個運算結果,直到數組遍歷完畢,最後得到的變量的值就是數組中只出現了一次的那個數字
public static int findOnceFrom2(int[] a) {
int len = a.length, res = 0;
for (int i = 0; i < len; i++) {
res = res ^ a[i];
}
return res;
}
2.2 有兩個不重複的數字
這個問題其實是基於以上問題的擴展,首先可知當只有一個數出現一次時,把數組中所有的數依次異或運算,最後剩下的就是落單的數,因爲成對出現的都抵消了。
- 按照這個思路,首先還是先異或,
最後剩下的數字肯定是A、B異或的結果 C,以數組 [1,2,2,1,3,5]爲例, 則 A=3(0011),B=5(0101),結果C=6(0110)
。C 的二進制表示中 1 所在的位,其實就是A 和 B 的二進制表示中數值不同的位
。我們取第一個1 所在的位數 index,可知是(0010 = 1<<index)即 index=1
,據此把原數組分成兩組,分組標準是數字第2位是否爲1。這樣成對的數字肯定在一個組中,因爲相同數字所有位的數值都相同,而不同的數肯定不在同一組。之後把這兩個組按照最開始的思路,依次異或,剩下的兩個結果就是這兩個只出現一次的數字
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if(array == null || array.length <= 1){
num1[0] = num2[0] = 0; // 初始化爲 0
return;
}
int len = array.length, index = 0, sum = 0;
for(int i = 0; i < len; i++){
sum ^= array[i];
}
for(index = 0; index < 32; index++){
if((sum & (1 << index)) != 0) break; // 獲取第一個 1 所在位數 index
}
for(int i = 0; i < len; i++){
if((array[i] & (1 << index))!=0){ // 根據 index 將數組分爲兩部分
num2[0] ^= array[i];
}else{
num1[0] ^= array[i];
}
}
System.out.println(num1[0]+" "+num2[0]);
}