標籤:style class blog code color get
題目:一個整型數組裡除了兩個數字之外,其餘的數字都出現了兩次,求這兩個只出現一次的數字
題解分析:
首先看到數字出現1次,出現2次,應該聯想到 異或運算:
0^a = a
a^a = 0
如果數組中只有一個數字出現奇數次,其餘都出現偶數次,我們就可以將這些數字全部異或,最後的結果即為所求(因為所有偶數次數字異或之後相消了)
但是:現在數組中有兩個只出現1次的數字,我們可不可以將原數組劃分為兩個子數組,子數組要求只能有一個數字出現1次,其餘都是偶數次
事實上是可以的,操作如下:
step1. 將原數組數字全部異或,結果記為M,因為偶數次數字全部抵消了,只剩下只出現1次的兩數字異或,結果肯定不為0,因為這兩個數字不同
結果M肯定不為0,那麼其二進位表示中就一定存在某位為1,我們就找到M中第一個為1的位置,記為第n位
step2. 我們現在以 數字第n位是否為1 為標準將原數組中的數字劃分為兩個子數組,這兩個子數組一定就是我們所希望的
因為出現偶數次的這些數,任意相同的數位二進位表示肯定是相同的,所以肯定會被分到同一組
最後只出現1次的兩個數a和b,因為異或結果第n位為1,那麼a和b的第n位一定是不同的(異或是 不同為1,相同為0)
step3, 對兩個子數組分別求出只出現1次的數字
int GetOnce(std::vector<int>& num){ assert(num.size() > 0); int result = 0; for (int i = 0; i < num.size(); ++i) { result ^= num.at(i); } return result;}// 找到num從右邊數起第一個是1的位unsigned int FindFirstBit1(int num){ unsigned int index = 0; while ((num & 1) == 0 && (index < 8 * sizeof(int))) { num >>= 1; ++index; } return index;}// 判斷數字num的第index位是不是1bool IsBit1(int num, unsigned int index){ num >>= index; return num & 1;}void GetTwoOnce(std::vector<int>& num){ if (num.size() == 0) return; int res = GetOnce(num); unsigned int bit = FindFirstBit1(res); int num1 = 0; int num2 = 0; for (int i = 0; i < num.size(); ++i) { if (IsBit1(num.at(i), bit)) { num1 ^= num.at(i); } else { num2 ^= num.at(i); } } std::cout << num1 << " " << num2 << std::endl;}