《劍指offer》——數組中只出現一次的數字

題目:一個整型數組裏除了兩個數字之外,其他的數字都出現了偶數次。要求找出這兩個 數字,且時間複雜度爲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];
    }
}
發佈了82 篇原創文章 · 獲贊 6 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章