面試題56 - i. 陣列中數字出現的次數
難度中等92收藏分享切換為英文關注反饋
乙個整型陣列nums
裡除兩個數字之外,其他數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。要求時間複雜度是o(n),空間複雜度是o(1)。
示例 1:
輸入:nums = [4,1,4,6]
輸出:[1,6] 或 [6,1]
示例 2:
輸入:nums = [1,2,10,4,1,4,3,3]
輸出:[2,10] 或 [10,2]
限制:
這道題需要對異或操作以及按位與或操作有所了解
相同的數字之間異或值為零(所有位都相等)
任何數字與0異或都等於本身(任何數與0異或都為本身)
即按位進行邏輯與操作,遵循公式(1&1=1,1&0=0,0&1=0,0&0=0)
其實現過程與異或相似
題幹:在陣列中,所有的數值都出現了兩次,只有唯一乙個數字出現了一次,找出這個數。
解答:將陣列中所有的數值進行異或操作,由於相等的數字異或之後都會歸零,零與任何數字異或都會得到該數字本身,所以最後異或的結果就是唯一的那個出現一次的數字。
經過前面的例子,我們知道了可以利用異或操作找出唯一的出現一次的數值,本題與引例的區別就是需要找到兩個不同的出現一次的數值,這個時候如果直接將所有的數值進行異或操作之後,得到的將是兩個只出現一次的數字(記為a,b)進行異或的結果,無法直接區分。
條件1:相同的數字在同一組中
條件2:只出現一次的兩個數字不在同一組中
如果能夠得到這樣的劃分,那麼本題就可以使用引例的做法分別對兩組資料進行操作就可以了。
這個時候需要明確兩個概念:
對於兩個相同的數字,他們對應二進位制表示的每一位都是相同的
對於兩個不同的數字,他們對應二進位制表示則一定有不同的位
由於我們最終要找的兩個數字a,b是不同的,所以這兩個數字的二進位制表示一定有不同的位,我們只需要把所有數字中這一位為0的劃為一組,這一位為1的劃為另一組,這個時候我們就發現這樣劃分的結果既可以使相同的數字在同一組中,又可以把a和b區分開。
此時我們只需要找到a和b的乙個二進位制表示不同的位就可以了
想找到這個位其實很簡單,我們可以直接將陣列中的數值進行一次異或操作,這樣就可以得到res = a⨁
\bigoplus
⨁b而res中值為1的位,一定是a和b二進位制表示不同的位(只有不同的數異或才會為1)
這樣基本就大功告成了,最後一步,要找到res中值為1的位,
首先:計算res&(00000001), 若結果為1,則res最低為為1,若不是,則繼續計算res&(00000010)判斷第二位。以此類推,由於a!=b,所以一定會找到某一位值為1
這樣整個流程就可以**實現了
class
solution
:def
singlenumbers
(self, nums: list[
int])-
> list[
int]
: res = functools.
reduce
(lambda x, y: x ^ y, nums)
mask =
1# 記錄a和b不同的位
while res & mask ==0:
mask <<=1
a, b =0,
0for num in nums:
if num & mask:
a ^= num
else
: b ^
= num
return
[a, b]
面試題56 I 陣列中數字出現的次數
乙個陣列,有兩個數字只出現一次,其他數字出現兩次,如何在o n 的複雜度,o 1 的空間複雜度情況下求出這兩個數字?這個題之前做校賽的時候做過,還是很簡單,由異或的性質,我們很容易得知道,把所有數字都異或一次,答案就是res a b 那倆單獨的數字的異或 那麼怎麼利用好這個res呢?由於本題不能開陣...
面試題56 I 陣列中數字出現的次數
乙個整型陣列 nums 裡除兩個數字之外,其他數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。要求時間複雜度是o n 空間複雜度是o 1 一看題目發現要求空間複雜度為o 1 一下子就徹底蒙了,本來打算用傳統的方法建立乙個大陣列,裡面有多少就加1,發現完全不行,想了半天沒有想出來結果,於是借鑑了...
面試題56 I 陣列中數字出現的次數
乙個整型陣列 nums 裡除兩個數字之外,其他數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。要求時間複雜度是o n 空間複雜度是o 1 示例 1 輸入 nums 4,1,4,6 輸出 1,6 或 6,1 示例 2 輸入 nums 1,2,10,4,1,4,3,3 輸出 2,10 或 10,2...