題目在這:https://leetcode-cn.com/problems/single-number-iii/
法一(哈希表):
直接使用哈希表。元素值為key 其出現的次數為value。直接周遊哈希表輸出value為1的key。
完整代碼:
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
from collections import Counter
hs = Counter(nums)
res = []
for i in hs:
if hs[i] == 1:
res.append(i)
return
法二 (異或位運算):
異或運算:
a ^ a = 0
a ^ b = 1
即相同為0,不同為1. 這裡的相同不同是在二進制下做的對位比較。
我們對整個字元串進行異或,隻會剩下兩個隻出現了一次的字元的異或結果。
比如字元串: aabbcddeff aa異或為0 bb異或為0.。。。。。最後隻會剩下c和e進行異或。我們拿到這個結果記為res。
我們重新周遊原字元串,使用某種方法對原來的字元串進行分類。是他們分成兩撥。這兩個隻出現一次的字母分别在不同的批次裡。 即 A批次隻有一個隻出現了一次的數字,其他都是一對一對的。B批同理。
那這個方法是什麼呢?
上面說過,異或二進制對位不同的情況下為1。由于結果res為兩個不同數字異或出來的結果,是以res的二進制數必然有1。我們需要找到這個數字1從右邊數的位置,設一個數 h = 1讓他和res不斷的進行 與 操作。 如果為0則讓h往左挪一位。右邊空出來的地方補0,這樣操作下去的結果就是h會變成 1後面跟着N個0。即此時已經找到了右邊數的第一個1的位置。
再簡單點說~這個所找到的1的位置,是兩個隻出現一次的數,這倆數在該位置上必然是一個為0一個為·1,異或出來就是結果為1.
是以重新周遊數組,讓h和每一個數進行 與 操作,必然可以将兩個隻出現一次的數分到不同的組中,其他一對一對的數配置設定的如何我們不考慮,隻要能吧兩個隻出現一次的數分開即可。
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
res = 0
for i in nums:
res ^= i # 将整個字元串異或
h = 1
while res & h == 0:
h = h << 1 # 找到從右邊數第一個出現的1的位置
a = 0
b = 0
for j in nums:
if h & j == 0: # 分類
a ^= j
else:
b ^= j
return [a,b]