思路:先看一個簡單的實例,若是找數組中只出現一次的一個數,其它的數都出現兩次,直接對數組元素進行位異或就可以得到數組中只出現一次的一個數。本題中,找數組中只出現一次的兩個數,則要將數組分成2個子數組,每個子數組中僅存在出現一次的一個數。關鍵就在於分組的標准,而對數組中所有的元素進行異或,得到的是這個數的異或。這個結果不為0,則一定存在某一個數字的一位為1,另一個數字中的某位為0,這樣異或的結果才不為0。因此分組的標准是對數組元素全部進行異或的結果中首位為1的那一位(假設是第N位)。然後以這個數與數組中元素進行與運算,進行分組。數組元素第N位為1的分一組,為0為另一組。在每個子數組中進行全部異或,最終可以得出數組中只出現一次的兩個數。
1 #include "stdafx.h" 2 3 unsigned int FindFirstBitIs1(int num); 4 bool IsBit1(int num, unsigned int indexBit); 5 6 void FindNumsAppearOnce(int data[], int length, int* num1, int* num2) 7 { 8 if(data == NULL || length < 2) 9 return; 10 11 int resultExclusiveOR = 0; 12 for(int i = 0; i < length ; ++ i) 13 resultExclusiveOR ^= data[i]; 14 15 unsigned int indexOf1 = FindFirstBitIs1(resultExclusiveOR); 16 17 *num1 = *num2 = 0; 18 for(int j = 0; j < length ; ++j) 19 { 20 if(IsBit1(data[j], indexOf1)) 21 *num1 ^= data[j]; 22 else 23 *num2 ^= data[j]; 24 } 25 } 26 27 // 找到num從右邊數起第一個是1的位 28 unsigned int FindFirstBitIs1(int num) 29 { 30 int indexBit = 0; 31 while( ((num & 1) == 0) && (indexBit < 8*sizeof(int)) ) 32 { 33 num = num >>1; 34 ++ indexBit; 35 } 36 37 return indexBit; 38 } 39 40 // 判斷數字num的第indexBit位是不是1 41 bool IsBit1(int num, unsigned int indexBit) 42 { 43 num = num >> indexBit; 44 return(num & 1); 45 } 46 47 int main() 48 { 49 int data[] = {2, 4, 3, 6, 3, 2, 5, 5}; 50 int length = sizeof(data) / sizeof(int); 51 52 int result1, result2; 53 FindNumsAppearOnce(data, length, &result1, &result2); 54 55 printf("%d %d\n", result1, result2); 56 57 return 0; 58 }