1,問題描述
一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。
2,解題思路
有兩種解題思路:
(1)桶排序
- 1)遍歷數組array,找到數組中最大值max;
- 2)構建輔助數組a,長度爲max+1;
- 3)遍歷數組array,array中的元素作爲a數組中的下標值,array中的元素每出現一次,a數組相對應下標的數組元素值加1(桶排序的思想);
- 4)遍歷a數組,a數組中,元素值等於1的下標值就是所求值。
該解題思路有個弊端,例如,假如數組中的元素值很大的情況下,輔助數組a就會很大,這樣佔用很多的輔助空間。
(2)異或 (轉自牛客)
- 1)首先明確異或運算的性質:兩個相同數字異或等於0,一個數和0異或還是它本身。
- 2)該問題的簡單版本:當只有一個數出現一次時,我們把數組中所有的數,依次異或運算,最後剩下的就是落單的數,因爲成對兒出現的都抵消了。
- 3)依照這個思路,我們來看兩個數(我們假設是AB)出現一次的數組。
- 我們首先還是先異或,剩下的數字肯定是A、B異或的結果,這個結果的二進制中的1,表現的是A和B的不同的位;
- 我們就取第一個1所在的位數( 從右向左方向中第一個1所在的位數,位數從0開始計數),假設是第3位,接着把原數組分成兩組。分組標準是第3位是否爲1。 如此,相同的數肯定在一個組,因爲相同數字所有位都相同,而不同的數,肯定不在一組。然後把這兩個組按照最開始的思路,依次異或,剩餘的兩個結果就是這兩個只出現一次的數字。
例如,按序遍歷原數組時,假如3在第一個組,那麼有兩個3的話,另一個3肯定也在第一組。
3,源碼
package manduner;
/**
* @author Manduner_TJU
* @version 創建時間:2019年6月26日上午10:40:29
*/
public class 數組中只出現一次的數字 {
public static void main(String[] args) {
int[] array = {2,4,3,6,3,2,5,5};
int[] num1 = new int[1];
int[] num2 = new int[1];
//FindNumsAppearOnce(array,num1,num2);
FindNumsAppearOnce2(array,num1,num2);
}
//方法二:異或
public static void FindNumsAppearOnce2(int[] array, int[] num1, int[] num2) {
int length = array.length;
if(length == 2){
num1[0] = array[0];
num2[0] = array[1];
return;
}
//計算異或結果
int bitResult = 0;
for(int i = 0; i < length; ++i){
bitResult ^= array[i];
}
int index = findFirst1(bitResult);
//按照第index位是否爲1的標準將原數組分成兩組,每一組分別做異或;
for(int i = 0; i < length; ++i){
if(isBit1(array[i], index)){
num1[0] ^= array[i];
}else{
num2[0] ^= array[i];
}
}
System.out.println(num1[0]);
System.out.println(num2[0]);
}
private static int findFirst1(int bitResult){
int index = 0;
while(((bitResult & 1) == 0) && index < 32){
bitResult >>= 1;
index++;
}
return index;
}
private static boolean isBit1(int target, int index){
return ((target >> index) & 1) == 1;
}
//方法一:桶排序
public static void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if(array==null||array.length<2) return;
int max = array[0];
for(int x : array){
if(x >= max){
max = x;
}
}
int[] a = new int[max+1];
for(int i=0;i<array.length;i++){
a[array[i]]++;
}
for(int j=0;j<=max;j++){
if(a[j]==1 && num1[0]==0){
num1[0] = j;
}else if(a[j]==1 && num2[0]==0){
num2[0] = j;
}else if(num1[0]!=0 && num2[0]!=0) {
break;
}
}
//System.out.println(num1[0]);
//System.out.println(num2[0]);
}
}