題目描述
給定一個非空整數數組,除了某個元素只出現一次以外,其餘每個元素均出現了三次。找出那個只出現了一次的元素。
說明:
你的算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?
示例 1:
輸入: [2,2,3,2]
輸出: 3
示例 2:
輸入: [0,1,0,1,0,1,99]
輸出: 99
解法1
與Leetcode 136 不同的是,136是 2n+1, 可以直接異或,而這題是3n+1 .既然是3n+1 的思路,用 set 去重之後,*3 減去 不去重直接sum 就是重複之數的兩倍 ,對應解法一,O(n) ,但是set 用到了額外空間,所以這並不是 最符合題目要求
的解法。
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
r = (3* sum(set(nums)) - sum(nums)) // 2
return r
解法2
如上所說,3n+1
與 2n+1
的區別在於 a ^ a
可以直接抵消,而 a ^ a ^a
不能直接抵消,如果找到 3數抵消
的運算方式就可以解決問題。
- 核心思路:可以看到 在
a,b = 0
的基礎上,遍歷nums ,得到 i 。通過a = (a^i) ; b= (b^i)
的操作 可以將 i 賦值給a,b
,所以推出右邊的運算表達式,
此時問題來了:當a =i時,b應該等於0 纔對啊,所以b= (b^i)
需要作出調整,b= (b^i) = i
,而i & ~i =0
,此時a=i
,所以i & ~a=0
,所以 運算表達式變爲
a = (a ^ i) & ~b
b = (b ^ i) & ~a
拿測試用例:[2,2,3,2]
推演,過程如下,最終返回a值,即爲重複值。
時間複雜度爲O(n) 。
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
a, b = 0, 0
for num in nums:
a = (a ^ num) & ~b
b = (b ^ num) & ~a
return a