給定乙個整數陣列 nums,其中恰好有兩個元素只出現一次,其餘所有元素均出現兩次。 找出只出現一次的那兩個元素。
示例 :
輸入: [1,2,1,3,2,5]
輸出: [3,5]
注意:結果輸出的順序並不重要,對於上面的例子, [5, 3] 也是正確答案。
你的演算法應該具有線性時間複雜度。你能否僅使用常數空間複雜度來實現?
首先是雜湊表,但是雜湊表沒有用到常數空間複雜度。
class
solution
:def
singlenumber
(self, nums: list[
int])-
> list[
int]:if
not nums:
return
num_dict =
# 這樣不是常數空間複雜度
for num in nums:
if num in num_dict:
del num_dict[num]
else
: num_dict[num]=1
a =for i in num_dict:
return a
位運算:
這道題與上道題一樣,是用到了位運算的技巧:
位運算的異或:異或具有交換律,所以一堆數,只要是相同的就會消除掉,只剩下不重複的。
因為本題有兩個不重複的數字,所以異或的最終結果不能體現乙個,但是我們可以通過某一位為1來看出這一位上,這兩個不重複的數是不同的,進而回到原來的陣列中,把原陣列分成兩個。
另外,得到某一位不為1的方法是:n & (-n) :-n 就是n的反碼+1【負數的補碼是對其原碼逐位取反,但符號位除外;然後整個數加1】
1110 0111 & 00011001 = 1
正數的反碼和補碼都與原數相等,負數的反碼是除了符號外,其餘取反;負數的補碼就是反碼加1.
5: 0000 0101 反碼: 0000 0101 補碼 0000 0101
-5: 1000 0101 反碼: 1111 1010 補碼: 1111 1011
計算機中二進位制是以補碼的形式儲存的,注意第一位最高位是符號位,正的為0,負的為1。如果是正的,補碼就是原碼,基本不用考慮額外的情況;如果是負的,要以補碼的形式,首先把原碼取反,再加1就得到補碼!!!!切記不要拿著原碼就來運算。計算機就是以補碼儲存的。比如-5,原碼是1000 0101,取反:1111 1010 (最高位不變)補碼是1111 1011,1的個數是7個!(位是計算機中資料儲存的最小單位,8 bit 就稱為乙個位元組(byte))
回歸正題:
# 老方法,所有都異或,再想辦法---所有異或之後。得到的結果如果某一位是1,那麼說明這兩個數的這一位是不同的,其他數的異或都歸0了,交換律。---所以利用這一位分開原陣列,就可以得到分別只有一位的兩個陣列,再異或得到最終的兩個數
class
solution
:def
singlenumber
(self, nums: list[
int])-
> list[
int]:if
not nums:
return
result =
0for num in nums:
result ^
= num
mask = result &
(-result)
# 找到最後一位為1的位
num1 =
0 num2 =
0for num in nums:
# 分成兩組
if num & mask ==0:
num1 ^
= num
else
: num2 ^
= num
return
[num1, num2]
(位運算)260 只出現一次的數字 III
給定乙個整數陣列 nums,其中恰好有兩個元素只出現一次,其餘所有元素均出現兩次。找出只出現一次的那兩個元素。示例 輸入 1,2,1,3,2,5 輸出 3,5 注意 結果輸出的順序並不重要,對於上面的例子,5,3 也是正確答案。你的演算法應該具有線性時間複雜度。你能否僅使用常數空間複雜度來實現?題解...
位運算 只出現一次的的數字
異或的兩個值 相同為假,不同為真 交換兩個整數的值時可以不用第三個引數a a b a b b b a b a乙個只出現一次的數字。乙個整型陣列裡除了乙個數字之外,其他的數字都出現了偶數次。請寫程式找出這個只出現一次的數字。int num 0 if array.length 0 return num ...
位運算 只出現一次的的數字
異或的兩個值 相同為假,不同為真 交換兩個整數的值時可以不用第三個引數a a b a b b b a b a乙個只出現一次的數字。乙個整型陣列裡除了乙個數字之外,其他的數字都出現了偶數次。請寫程式找出這個只出現一次的數字。int num 0 if array.length 0 return num ...