[算法][經典面試題]數組中只出現一次的數字|變體題目(一個不重複、二個不重複)

1. 原題

一個整型數組裏除了一個數字之外,其他的數字都出現了兩次。請寫程序找出這一個只出現一次的數字。

解題思路:利用異或操作的性質可以快速解決這個問題。

異或運算法則

  1. a ^ 0 = a——與00異或等於自身;
  2. a ^ a = 0——與自身異或等於00
  3. a ^ b ^ c = a ^ c ^ b——交換律;
  4. a ^ b = c <=> a ^ c = b <=> b ^ c = a

代碼如下,複雜度O(n)O(n):

from functools import reduce
res = reduce(lambda x, y: x ^ y, array)
print(res)

2. 變體

一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。

變體難度與解決思路

由於這一次變成了需要找到兩個思路,如果還按照原題進行異或操作,則兩個不重複的數會進行異或疊加,需要將異或疊加的狀態值拆解出來;根據異或運算法則4,則必須知道其中一個不重複數字才能拆解出另一個。

於是,考慮第一輪異或得到的結果res,其二進制表示中,取得1的位,不重複數字aabb在該位上比不相同(根據異或運算0^1=1得知);那麼找到第一個不相同的位,根據是否與該位相同把原數列劃分爲兩份,則分別包含aabb,再根據上一問中的解法進行求解即可,算法複雜度爲O(2n)O(2*n)(可以進一步優化到O(3n2)O(\frac{3n}{2}))。

def find( array):
    res = reduce(lambda x, y: x ^ y, array)
    # 異或結果中爲1的是不重複數字a和b不同的位
    index, res_store = 1, res  # index取第一個遇見的1,根據此位把array劃分爲兩組再異或
    while res & 0b1 != 1:
        res, index = res >> 1, index << 1

    # 跟不重複數字a在index位上相同的數字列表
    a = reduce(lambda x, y: x ^ y, filter(lambda x: x & index, array))
    return a, a ^ res_store  # 根據 a^b=c <=> a^c=b
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章