原題:260. 只出現一次的數字 III (leetcode)
題目描述
給定一個整數數組 nums
,其中恰好有兩個元素只出現一次
,其餘所有元素均出現兩次。 找出只出現一次的那兩個元素。
示例 : 輸入: [1,2,1,3,2,5] 輸出: [3,5]
注意:
結果輸出的順序並不重要,對於上面的例子, [5, 3] 也是正確答案。
你的算法應該具有線性時間複雜度。你能否僅使用常數空間複雜度來實現?
分析
我們可以利用雙層循環以O()的時間複雜度,O(1)的空間複雜度來解決,但是不符合要求;當然我們也可以利用Hash字典數據結構在O(n)的時間複雜度,O(n)的空間複雜度來解決,但是依然不符合要求;
於是我們根據163題中異或的思想來解決:
- 全部元素異或消掉出現兩次的數字. 異或的結果爲
s
. - 尋找
s
的lowbit
值.lowbit(s)
爲s
的二進制表達式中最右邊的1所對應的值
. 因此lowbit(s)
二進制表達式中只有一個bit 1
.
lowbit(s) = s & -s
例如: s=1010
lowbit(s) = 1010 & 0110 = 0010 = 2
- 用
lowbit(s)
將數組分成兩組. 一組中,元素A[i] & lowbit(s) == lowbit(s)
, 即包含lowbit(s)的bit 1
. 剩餘的是另一組.
而且,兩個不同數也一定分在不同組
. 因爲異或值s
中的bit1
就是因爲兩個數字的不同而貢獻的. 同一組的元素再異或求出不同數字
. 出現兩次的數字
, 肯定出現同一組
,異或後消除掉
.也就是說結果二進制只存在一個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