萬綠叢中一點紅 落單的數字 Single Number III_二進位操作_Leetcode #260

更新於 發佈於 閱讀時間約 4 分鐘

題目敘述 Single Number III

給定一個輸入陣列,已知有兩個烙單的數字,其他剩餘的數字都恰巧出現兩次。

找出這兩個烙單的數字

題目額外提出限制,請使用O(n)線性時間、O(1)常數空間複雜度的演算法。


測試範例

Example 1:

Input: nums = [1,2,1,3,2,5]
Output: [3,5]
Explanation: [5, 3] is also a valid answer.
35就是烙單,只有出現一次的數字。

Example 2:

Input: nums = [-1,0]
Output: [-1,0]

Example 3:

Input: nums = [0,1]
Output: [1,0]

約束條件

Constraints:

  • 2 <= nums.length <= 3 * 10^4

輸入陣列長度介於2~三萬之間。

  • -2^31 <= nums[i] <= 2^31 - 1

每個陣列元素都在4byte整數範圍內。

  • Each integer in nums will appear twice, only two integers will appear once.

只有恰好兩個數字烙單,其他剩餘的數字都剛好出現兩次。


觀察

如果最直覺的想法,就是用字典去記錄每個數字的出現次數。找出出現次數只有一次的數字即可。

演算法 二進位操作

但是,困難點在於題目多了額外拘束,限定使用O(1)常數空間。

可以怎麼做呢?


兩個烙單的數字代表兩個相異的數字,都只出現一次。

那麼,可以先找出兩個烙單數字相異的bit作為遮罩,
再用XOR過濾掉剩餘都出現兩次的數字(A XOR A = 0)
最後留下來的數字,恰好就是那兩個烙單的數字。


程式碼 二進位操作

from functools import reduce

class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:


xor = lambda x,y : x^y

xor_result = reduce( xor, nums)

# mask is the right-most 1 of xor result
# use mask to separate nums into two groups, one group contains single_num_a, the other contains single_num_b
mask = xor_result & -xor_result

single_num_a, single_num_b = 0, 0

for number in nums:
# separate and collect these two single numbers by masking

if mask&number:
single_num_a ^= number
else:
single_num_b ^= number

return [single_num_a, single_num_b]

複雜度分析

時間複雜度:O(n)

從左到右,掃描每個數字,每個數字計算一次。


空間複雜度: O(1)

使用到的都是固定尺寸的臨時變數,為常數級別O(1)。


Reference

[1] Single Number III - LeetCode

avatar-img
91會員
425內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
本文章複習了滑動窗口Sliding window的框架, 並且使用滑動窗口來解修改後,最長相等子字串的長度。 給定兩個字串s和t,還有對應的預算上限cost。 每修改一個字元就要付出對應的ASCII Code距離成本。 請問修改後s 和 t 最長的相等子字串長度是多少?
給定一個輸入非負整樹陣列nums,請找出k值,使得陣列中恰好有k個元素大於等於 k。如果無解,回傳-1。尋找k值的方法包括排序法和二分搜尋法,時間複雜度都為O(n log n),空間複雜度為O(1)。關鍵知識點是當解空間具有遞增或遞減的性質時,可以用二分搜尋法加快搜尋效率。
探討如何使用DP動態規劃的方法來進行單字串接,包含了DP遞迴關係式、狀態定義、優化技巧和程式碼示例。同時分析了時間複雜度、空間複雜度和關鍵知識點。這是LeetCode的一個應用題,類似於Word Break I的延伸。
知道如何從一組給定的英文字母和單字庫中的單字拼出最高分的單字組合。使用DFS + 回溯法 + 剪枝優化的演算法,詳細分析瞭如何展開所有可能的路徑,並且找出符合條件的狀態,協助讀者理解演算法背後的思維和方法。
本篇文章介紹了區間DP及博弈論Min/Max最佳化的相關概念,以及如何應用這些概念來計算最佳策略進行取石頭遊戲的模擬。文章實際分析了演算法、實用的加速技巧和關鍵知識點。這篇文章對於想要學習區間DP的讀者來說非常有價值。
子集合生成是一道經典的組合類上機考和面試題目。本篇文章介紹多個不同的解決方案,以及相關演算法框架。主要目標是給定n個相異的元素,產生所有的子集合。
本文章複習了滑動窗口Sliding window的框架, 並且使用滑動窗口來解修改後,最長相等子字串的長度。 給定兩個字串s和t,還有對應的預算上限cost。 每修改一個字元就要付出對應的ASCII Code距離成本。 請問修改後s 和 t 最長的相等子字串長度是多少?
給定一個輸入非負整樹陣列nums,請找出k值,使得陣列中恰好有k個元素大於等於 k。如果無解,回傳-1。尋找k值的方法包括排序法和二分搜尋法,時間複雜度都為O(n log n),空間複雜度為O(1)。關鍵知識點是當解空間具有遞增或遞減的性質時,可以用二分搜尋法加快搜尋效率。
探討如何使用DP動態規劃的方法來進行單字串接,包含了DP遞迴關係式、狀態定義、優化技巧和程式碼示例。同時分析了時間複雜度、空間複雜度和關鍵知識點。這是LeetCode的一個應用題,類似於Word Break I的延伸。
知道如何從一組給定的英文字母和單字庫中的單字拼出最高分的單字組合。使用DFS + 回溯法 + 剪枝優化的演算法,詳細分析瞭如何展開所有可能的路徑,並且找出符合條件的狀態,協助讀者理解演算法背後的思維和方法。
本篇文章介紹了區間DP及博弈論Min/Max最佳化的相關概念,以及如何應用這些概念來計算最佳策略進行取石頭遊戲的模擬。文章實際分析了演算法、實用的加速技巧和關鍵知識點。這篇文章對於想要學習區間DP的讀者來說非常有價值。
子集合生成是一道經典的組合類上機考和面試題目。本篇文章介紹多個不同的解決方案,以及相關演算法框架。主要目標是給定n個相異的元素,產生所有的子集合。
你可能也想看
Google News 追蹤
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~