[LeetCode] Single Number III 單獨的數字之三


 

Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.

Example:

Input:  [1,2,1,3,2,5]
Output: [3,5]

Note:

  1. The order of the result is not important. So in the above example, [5, 3] is also correct.
  2. Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?

 

這道題是之前那兩道 Single Number 和 Single Number II 的再次延伸,說實話,這類位操作 Bit Manipulation 的題,如果之前沒有遇到過類似的題目,楞想是很難相出來的,於是我只能上網搜大神們的解法,發現還真是巧妙啊。這道題其實是很巧妙的利用了 Single Number 的解法,因為那道解法是可以准確的找出只出現了一次的數字,但前提是其他數字必須出現兩次才行。而這題有兩個數字都只出現了一次,那么我們如果能想辦法把原數組分為兩個小數組,不相同的兩個數字分別在兩個小數組中,這樣分別調用 Single Number 的解法就可以得到答案。那么如何實現呢,首先我們先把原數組全部異或起來,那么我們會得到一個數字,這個數字是兩個不相同的數字異或的結果,我們取出其中任意一位為 ‘1’ 的位,為了方便起見,我們用 a &= -a 來取出最右端為 ‘1’ 的位,具體來說下這個是如何操作的吧。就拿題目中的例子來說,如果我們將其全部 '異或' 起來,我們知道相同的兩個數 '異或' 的話為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產生影響。分別將兩個小組中的數字都異或起來,就可以得到最終結果了,參見代碼如下:

 

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;
    }
};

 

類似題目:

Single Number II

Single Number

 

參考資料:

https://leetcode.com/problems/single-number-iii/

https://leetcode.com/problems/single-number-iii/discuss/68900/Accepted-C%2B%2BJava-O(n)-time-O(1)-space-Easy-Solution-with-Detail-Explanations

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM