缺失的第一個正數解法


  這個題目是我在leetcode上見過的一個題目,感覺官方解答寫的不太好,就特地寫一篇文章,自己也加深理解。

題目描述

給定一個未排序的整數數組,找出其中沒有出現的最小的正整數。

示例 1:
輸入: [1,2,0]
輸出: 3

示例 2:
輸入: [3,4,-1,1]
輸出: 2

示例 3:
輸入: [7,8,9,11,12]
輸出: 1

題目分析

  又是考這種是否出現的問題,我們很直觀的想到哈希表,使用一個標記,記錄是否出現,當然也可以直接使用集合,來判斷是否出現。題目中要求找沒有出現的最小的正整數,所以我們只需要關心正整數即可,對於負數,壓根可以不用理會了。
  如果說數組的長度是n的話,那麼顯然,可以斷定,最小未出現的正整數一定小於等於n+1。這個很好理解,不多贅述。所以我們只需要關心1~n+1之間的數是否出現即可,直接使用哈希表或者哈希集合實現即可。

python 代碼

def firstMissingPositive(nums: List[int]) -> int:
    s = set()
    n = len(nums)
    for num in nums:
        if num > 0 and num <= n:
            s.add(num)
    for i in range(1, n + 2):# 判斷1~n+1是否出現
        if i not in s:
            return i

  但是除了哈希表,我們還有一種通過數組來實現哈希表的方式,我們只關心1~n+1是否出現,我們可以直接使用索引來映射,在長度爲n的數組中用下標i來判斷數組是否出現了i+1。通過數組來實現哈希表是一種很常用的方式,一般用於哈希表的鍵很有限,很容易和數組的下標建立映射的情況

python代碼

def firstMissingPositive(nums: List[int]) -> int:
    n = len(nums)
    appear = [0] * (n+1)
    for num in nums:
        if num > 0 and num <= n:
            appear[num - 1] += 1  # 用數組實現哈希,數字的值-1作爲鍵
    for i, num in range(n+1):
        if appear[i]== 0: # 說明i+1沒有出現
            return i + 1

  但是以上兩種情況下,都佔用了額外的空間,容易分析,以上的方式時間複雜度是O(n)O(n),空間複雜度也都是O(n)O(n),有沒有時間複雜度或者空間複雜度更好的模式,答案是有的。我們可以在空間複雜度上做文章,我們注意到原來的數組長度是n,我們建立哈希表的數組長度也是n,我們能否直接在原來的數組上建立哈希表。
  我們仍然是不關心數字小於等於0或者大於n的情況,所以出現這些數字可以直接丟了,給哈希表騰地方了。但是如果你把一個值移到哈希表中對應的位置,數字-1的下標處,如果原來就有數字怎麼辦,那麼就把這兩個數字交換,然後繼續移動。
  舉個例子,數組中是12453,我們對比1的位置正好是其哈希表所需要存儲的位置,下標等於值-1,不用移動,同樣2不用移動,4應該出現在下標爲3的位置,所以我們把4和下標爲(4-1)的數字交換,得到12543,然後此時下標爲3的數字是5,我們再把5和下標爲4的數字交換,顯然,我們需要交換的次數最多是n次,比較的次數最多是2n次,所以這樣時間複雜度就是O(n)O(n)了,因爲在原數組上修改,空間複雜度是常數級別,所以就是O(1)O(1)

python代碼

def firstMissingPositive(nums: List[int]) -> int:
    j, n = 0, len(nums)
    while j < n:
        i = nums[j]
        if i > 0 and i <= n and j + 1 != i and nums[i - 1] != i:
            nums[i - 1], nums[j] = nums[j], nums[i - 1]
            continue
        j += 1

  注意到代碼中,我們直接在對應位置村上下標+1的數字,表示這個數字出現了,如果不滿足這個關係,我們認爲這個位置的數字沒有出現。注意道代碼中最後一個判斷num[i-1]!=i表示到目前位置i還沒有出現就交換,反之,說明i已經放置在正確的位置,就不需要將當前的數字放到那個位置了。如果沒有這個判斷,會在兩個相同的數之間死循環。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章