leetcode位運算學習筆記 只出現一次的數字

2021-10-07 11:27:00 字數 1942 閱讀 4725

給定乙個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素(使用常數空間)。

1、結合律:(a ^ b) ^ c = a ^ (b ^ c)

2、對於任何數x,都有x ^ x = 0,x ^ 0 = x

初始化乙個元素a=0,與所有元素做一次異或,即可得到只出現一次的元素

class

solution

:def

singlenumber

(self, nums: list[

int])-

>

int:

a =0for num in nums:

a ^= num

return a

給定乙個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現了三次。找出那個只出現了一次的元素。(使用常數空間)

基本思路還是借助異或運算來消除相同元素,但是由於每個元素出現了三次,需要另外借助乙個變數b。

陣列中的數字出現的次數為1或3;為了找出出現一次的數字,出現三次的數字異或運算之後,結果必須為0,出現一次的數字經過異或運算之後結果是他本身。用**表示:

if b ==0:

if n ==0:

a= a

if n ==1:

a=~aif b==1:

a=0

class

solution

:def

singlenumber

(self, nums: list[

int])-

>

int:

a, b =0,

0for num in nums:

a = a ^ num &

~b b = b ^ num &

~a return a

給定乙個整數陣列 nums,其中恰好有兩個元素只出現一次,其餘所有元素均出現兩次。 找出只出現一次的那兩個元素。(使用常數空間)。

和136題的區別在於這個陣列有兩個只出現一次的數,所以可以借鑑。關鍵就是把陣列分成兩個部分,每個部分包含乙個只出現一次的數字。

那麼怎麼把陣列分成兩部分呢?

這裡陣列所有元素都做一次異或運算的話,得到的結果是兩個只出現一次的數字的異或結果s。要把這兩個數字分開,可以在s的二進位制表示中找到乙個1,因為異或相同為0,相異為1,意味著這兩個只出現一次的數的二進位制表示是不同的,根據這個就可以把陣列分成兩個部分,至於其他出現兩次的數,也按照這個規則分成兩撥,不會影響結果。

那麼,怎麼找到異或結果中的1呢?

這裡使用了s&(-s)得到二進位制數s最低位的1,其他位置零.至於為啥是這樣(我也是看了其他題解的,反正我想不到)

得到劃分陣列的那個數之後,遍歷陣列,把其中一類做異或運算得到的結果就是乙個只出現一次的數;再把它和兩個只出現一次的數 的異或結果(就是原陣列元素的異或結果)做一次異或運算,根據異或運算的結合律,可以得到另乙個只出現一次的數。

class

solution

:def

singlenumber

(self, nums: list[

int])-

> list[

int]

: a =

0for num in nums:

a ^= num

diff = a &

(-a)

# 保留二進位制數a最低位的1

b =0for num in nums:

if diff & num:

# 相當於把原陣列分組

b ^= num

return

[b, b^a]

位運算學習筆記

1.補碼 補碼是為了表示乙個負數的二進位制形式。其轉化方式是,先將負數當成正數,轉化成二進位制的形式,再將二進位制正數的各個位上取反,再加上 例如 5先求出5的二進位制數 0000 0000 0101 然後將各個位上0變1 1變0 1111 1111 1010 最後再加1 1111 1111 101...

位運算學習筆記

要明白位運算是在二進位制中的運算方式,所有其他進製的數在進行位運算時都要先轉化成二進位制數再進行運算。int 是 32位二進位制。有符號整型 正數 0 負數 1 1 00000.0001 1 10000.00011.按位與 只有當x,y都是1的時候,運算結果才是1,其餘情況都是0.1 1 1 1 0...

位運算學習筆記

1 二進位制最高位是符號位 0代表正數,1代表負數 2 正數的原碼 反碼 補碼都相同 3 負數的反碼是將原碼符號位不變,其他位取反。4 負數的補碼是將反碼 1 5 0的原碼 補碼都是0 6 計算機中是依據補碼進行計算的。7 練習 1 2 例題說明 對2按位取反。由於2為正數,正數的原碼 補碼相等。所...