首先來看題目要求:
在乙個陣列中除兩個數字只出現1次外,其它數字都出現了2次, 要求盡快找出這兩個數字。
考慮下這個題目的簡化版——陣列中除乙個數字只出現1次外,其它數字都成對出現,要求盡快找出這個數字。這個題目在之前的《
位操作基礎篇之位操作全面總結
》中的「位操作趣味應用」中就已經給出解答了。根據異或運算的特點,直接異或一次就可以找出這個數字。
現在陣列中有兩個數字只出現1次,直接異或一次只能得到這兩個數字的異或結果,但光從這個結果肯定無法得到這個兩個數字。因此我們來分析下簡化版中「異或」解法的關鍵點,這個關鍵點也相當明顯——陣列只能有乙個數字出現1次。
設題目中這兩個只出現1次的數字分別為a和b,如果能將a,b分開到二個陣列中,那顯然符合「異或」解法的關鍵點了。因此這個題目的關鍵點就是將a,
b分開到二個陣列中。由於a,b肯定是不相等的,因此在二進位製上必定有一位是不同的。根據這一位是0還是1可以將a,b分開到a組和b組。而這個陣列中其它數字要麼就屬於a組,要麼就屬於b組。再對a組和b組分別執行「異或」解法就可以得到a,b了。而要判斷a,b在哪一位上不相同,只要根據a異或b的結果就可以知道了,這個結果在二進位製上為1的位都說明a,b在這一位上是不相同的。
比如int a =
整個陣列異或的結果為3^5即0x0011 ^ 0x0101 = 0x0110
對0x0110,第1位(由低向高,從0開始)就是1。因此整個陣列根據第1位是0還是1分成兩組。
a[0] =1 0x0001 第一組
a[1] =1 0x0001 第一組
a[2] =3 0x0011 第二組
a[3] =5 0x0101 第一組
a[4] =2 0x0010 第二組
a[5] =2 0x0010 第二組
第一組有,第二組有,明顯對這二組分別執行「異或」解法就可以得到5和3了。
分析至些,相信**不難寫出,下面給出完整的源**:
[cpp]view plain
copy
//陣列中除兩個數字外,其它數字都出現了次。要求盡可能快的找出這兩個數字
//by morewindows (
#include
void
findtwonotrepeatnumberinarray(
int*a,
intn,
int*pn1,
int*pn2)
void
printfarray(
inta,
intn)
intmain()
;int
a[maxn] = ;
printf("陣列為: \n"
);
printfarray(a, maxn);
intnnotrepeatnumber1, nnotrepeatnumber2;
findtwonotrepeatnumberinarray(a, maxn, &nnotrepeatnumber1, &nnotrepeatnumber2);
printf("兩個不重複的數字分別為: %d %d\n"
, nnotrepeatnumber1, nnotrepeatnumber2);
return
0;
}
執行結果如下所示:
陣列中只出現1次的兩個數字
乙個整型陣列裡除了2個數字分別出現1次之外,其他的數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。要求時間複雜度是o n 空間複雜度是o 1 如果我們能把問題中的陣列分成2個子陣列,使得每個子陣列中都只有乙個唯一的元素以及很多成對的元素,那麼我們就可以求出每個子陣列中唯一的元素,最終就可以得到...
陣列中只出現一次的兩個數字
乙個整型陣列裡除了兩個數字之外,其他的數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。你可以假設這兩個數字一定存在。樣例輸入 1,2,3,3,4,4 輸出 1,2 解決方案 異或 兩個相同的元素異或 設出現一次的數字分別為x和y 1,先用乙個sum 將整個陣列遍歷一遍同時異或該陣列元素與sum...
陣列中只出現一次的兩個數字
我們知道如果出現一次的數只有1個,其餘的都出現了兩次,那麼,直接異或一遍就可以了,但是,此題有2個 所以,異或一遍的結果為x y,即出現一次的兩個數異或的結果,從s x y 0,知道s的某位為1,x與y的在s為1的位不一樣,這樣就可以將數分為兩個集合,與s相同位為1的和s相同位為0的,x與y一定在兩...