&LeetCode260& 只出現一次的數字 III

題目

給定一個整數數組 nums,其中恰好有兩個元素只出現一次,其餘所有元素均出現兩次。 找出只出現一次的那兩個元素。

示例 :
輸入: [1,2,1,3,2,5]
輸出: [3,5]

注意:
結果輸出的順序並不重要,對於上面的例子, [5, 3] 也是正確答案。
你的算法應該具有線性時間複雜度。你能否僅使用常數空間複雜度來實現?

來源:力扣(LeetCode

思路

首先,將其全部位進行 ‘異或’ ,我們知道相同的兩個數 ‘異或’ 的話爲0,那麼數組中的1和2,都抵消掉了,就剩3和5 ‘異或’ 起來,那麼就是二進制的 11 和 101 ‘異或’ ,得到110。
然後,進行 a &= -a 操作。首先變負數吧,在二進制中負數採用補碼的形式,而補碼就是反碼 +1,那麼 110 的反碼是 11…1001,那麼加1後是 11…1010,然後和 110 相與,得到了 10,就是代碼中的 diff 變量。得到了 diff,就可以將原數組分爲兩個數組;
如果兩個相同的數字 ‘異或’ ,每位都會是0,而不同的數字 ‘異或’ ,一定會有對應位不同,一個0一個1,這樣 ‘異或’ 是1。
比如3和5的二進制 11 和 101,如果從低往高看,最開始產生不同的就是第二位,用第二位來和數組中每個數字相與,根據結果的不同,一定可以把3和5區分開來;
而其他的數字由於是成對出現,所以區分開來也是成對的,最終都會 ‘異或’ 成0,不會3和5產生影響;
分別將兩個小組中的數字都異或起來,就可以得到最終結果。

C++代碼

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) 
    {
        int diff = accumulate(nums.begin(), nums.end(), 0, bit_xor<int>());
        diff &= -diff;
        vector<int> res(2, 0);
        for (auto &a : nums)
        {
            if (a & diff)
                res[0] ^= a;
            else
                res[1] ^= a;
        }
        return res;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章