寫在前面
我們不是計算機專業的,卻一直對計算機演算法感興趣,也一直致力於減小自己程式的複雜度[捂臉],昨日吃飯時,某老鐵考我一道演算法題,思索良久,輾轉反側,夜不能寐,遂厚著臉皮去問答案,然則令吾汗顏,果真是一波騷操作……
看題!
給定一個非空整數陣列, 除了某個元素只出現一次以外, 其餘每個元素均出現兩次, 找出那個只出現了一次的元素。
說明:
你的演算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?
示例 1:
輸入: [2,2,1]
輸出: 1
示例 2:
輸入: [4,1,2,1,2]
輸出: 4
看答案之前,不妨獨立思考一下,看看能不能想出解決方案!
推薦先想一會兒!
如果實在想不出來, 可以看一下提示 繼續想 !!
提示
看一下標題!!!
題目解析
根據題目描述,由於加上了時間複雜度必須是O(n),並且空間複雜度為O(1)的條件,因此不能用排序方法,也不能使用map資料結構。
我們想了一晚上,結果, 答案是使用 位操作Bit Operation 來解此題。
將所有元素做異或運算,即 a[1] ⊕ a[2] ⊕ a[3] ⊕...⊕ a[n]
,而結果就是那個只出現一次的數字,時間複雜度為O(n)。
什麼??你忘記了異或???
異或運算 A ⊕ B
的真值表如下:
A | B | A ⊕ B |
---|---|---|
False | False | False |
True | True | True |
True | False | True |
False | True | True |
即:不相等即為True
而兩個相等 的數做異或操作為0
而任何數與0
做異或操作都等於其本身
題目進階
有一個 n 個元素的陣列,除了兩個數只出現一次外,其餘元素都出現兩次,讓你找出這兩個只出現一次的數分別是幾,要求時間複雜度為 O(n) 且再開闢的記憶體空間固定(與 n 無關)。
示例 :
輸入: [1,2,2,1,3,4]
輸出: [3,4]
題目再解析
根據前面找 一個 不同數的思路演算法,在這裡把所有元素都異或,那麼得到的結果就是那兩個只出現一次的元素異或的結果, 為了敘述方便, 我們這裡把這個結果簡單記為字母 K
。
因為這兩個只出現一次的元素一定是不相同的,所以 K
一定不為零, 將K
從左往右數的第一個為1的位記錄下來。
再然後,以這一位是 1 還是 0 為標準,將陣列的 n 個元素分成兩部分。
將這一位為 0 的所有元素做異或,得出的數就是隻出現一次的數中的一個
將這一位為 1 的所有元素做異或,得出的數就是隻出現一次的數中的另一個。
這樣就解出題目, 忽略尋找不同位的過程,總共遍歷陣列兩次,時間複雜度為O(n)。
舉個例子吧
假如:
輸入是: [1,2,2,1,3,4,7,7]
進行異或操作:
>>> 1^2^2^1^3^4 # python的異或操作符
7
異或完畢為7
即0000 0111
數字7
從左往右數的第一個為1的位為
0000 0111
^
也就是第六位
以這一位是 1 還是 0 為標準,將陣列的 n 個元素分成兩部分
(也就是陣列大於等於4
的分一組, 小於4
的分一組)
即[4, 7, 7] 和 [1,2,2,1,3]
>>> # 陣列[4,7,7]所有元素做異或操作
>>> 4^7^7
4
>>> 陣列[1,2,2,1,3]所有元素做異或操作
>>> 1^2^2^1^3
3
大功告成!!
據該老鐵說此題來源於 LeetCode
第 136 號問題:https://leetcode-cn.com/probl...