題目描述:
一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。
實現如下:
//關鍵點是使用異或位運算符
//相同的數字異或結果爲零
//如果數組中只有一個數字出現一次,那麼異或的遍歷這個數組,最後的結果就是那個數字
//如果此時變成有兩個數字都出現了一次,那還按照之前的辦法,最後的結果就是這兩個數字的異或值
//解決方法:
//將數組異或的遍歷,求其結果的第一個爲1的位數
//因爲這一位是兩個數字之間不同的位,即一箇中位,另一箇中爲0
//再一次遍歷數組,判斷所有的元素這一位是否爲1,並按此分爲兩組
//組內再將所有的元素異或,最終的值即爲只出現一次的數字
//因爲出現兩次的數字,都會被分到同一組,所以異或時就抵消了
class Solution
{
public:
unsigned int xorIndexResult(int xorResult)
{
unsigned int index = 0;
//當位數小於32爲且此爲不爲1時,繼續計算
while (index < 8 * sizeof(xorResult) && ((xorResult & 1) == 0))
{
xorResult = xorResult >> 1;
++index;
}
return index;
}
void FindNumsAppearOnce(vector<int> data, int* num1, int *num2)
{
if (data.size() < 2)//防禦性動作
return;
int xorResult = 0;//記錄整個數組的異或結果
for (int i = 0; i < data.size(); ++i)
xorResult ^= data[i];
//計算異或結果中,第一個值爲1的位數
unsigned int xorIndex = xorIndexResult(xorResult);
for (int j = 0; j < data.size(); ++j)
{
int tmp = data[j];
tmp = tmp >> xorIndex;//計算所有元素此位的值,並進行分組
if (tmp & 1)
*num1 ^= data[j];//組內再進行異或計算
else
*num2 ^= data[j];
}
}
};