位運算-040-數組中只出現一次的數字


原題:260. 只出現一次的數字 III (leetcode)

題目描述

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

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

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

分析

我們可以利用雙層循環以O(n2n^2)的時間複雜度,O(1)的空間複雜度來解決,但是不符合要求;當然我們也可以利用Hash字典數據結構在O(n)的時間複雜度,O(n)的空間複雜度來解決,但是依然不符合要求;

於是我們根據163題中異或的思想來解決:

  1. 全部元素異或消掉出現兩次的數字. 異或的結果爲s.
  2. 尋找slowbit值. lowbit(s)s二進制表達式中最右邊的1所對應的值. 因此lowbit(s)二進制表達式中只有一個bit 1.
    lowbit(s) = s & -s
    例如: s=1010
    lowbit(s) = 1010 & 0110 = 0010 = 2
  3. lowbit(s)將數組分成兩組. 一組中,元素A[i] & lowbit(s) == lowbit(s), 即包含lowbit(s)的bit 1. 剩餘的是另一組.
    而且,兩個不同數也一定分在不同組. 因爲異或值s中的bit1就是因爲兩個數字的不同而貢獻的.
  4. 同一組的元素再異或求出不同數字. 出現兩次的數字, 肯定出現同一組, 異或後消除掉.也就是說結果二進制只存在一個1,就是n最低位的1.

代碼

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        s = 0
        for i in nums:
            s ^= i
        
        mask = s&(-s)

        res1 = 0
        res2 = 0
        for i in nums:
            if i&mask == mask:
                res1 ^= i
            else:
                res2 ^= i
        
        return res1,res2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章