題目:一個整型數組裏除了兩個數字之外,其他的數字都出現了偶數次。要求找出這兩個 數字,且時間複雜度爲O(n),空間複雜度爲O(1)。
如果題目中數組中只出現一次的數字只有一個,那麼可以依次將數組中的每個數字進行異或操作,那麼其他出現偶數次的數字會因爲自身與自身的異或而被消除,則最終的結果爲那個只出現一次的數字。
當只出現一次的數字爲兩個時,最終的結果是這兩個數字異或之後的結果。因爲這兩個數字不相等,那麼最終異或的結果中至少有一位爲1。可以在結果數字中找到第一個爲1的位的位置,記作第n位,這兩個不同的數字在該位上的值一定不同。所以可以根據第n位是否爲1將數組分爲兩部分,則出現了偶數次的數字一定會被分在同一組,且只出現一次的兩個數字分別被分配在數組的兩部分。
/*數字中第一次出現1的位置,從右到左,由低位到高位*/
unsigned int FindFirstBitIs1(int num)
{
int index = 0;
while((num & 1) == 0 && (index < 8 * sizeof(int)))
{
num = num >> 1;
index++;
}
return index;
}
/*數字在index位置上的值是否爲1*/
bool IsBit1(int num, int index)
{
num = num >> index;
return(num & 1);
}
/*查找數組中只出現一次的數字*/
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2)
{
if(data.empty() || data.size() < 2 || num1 == NULL || num2 == NULL)
return;
int result = 0;
//將所有數字相互異或
for(int i = 0; i < data.size(); i++)
result ^= data[i];
//找到結果中1第一次出現的位置
unsigned int indexOf1 = FindFirstBitIs1(result);
*num1 = *num2 = 0;
for(int j = 0; j < data.size(); j++)
{
//根據index位置上的值是否爲1將數組分爲兩部分
//並將兩部分數字分別互相異或
//兩部分數字異或最終的結果分別爲數組中只出現一次的兩個數字
if(IsBit1(data[j], indexOf1))
*num1 ^= data[j];
else
*num2 ^= data[j];
}
}