1. 程式人生 > >Leetcode演算法——41、尋找缺失的正數

Leetcode演算法——41、尋找缺失的正數

給定一個亂序的整數陣列,找到最小的缺失的正整數。

示例:

Example 1:
Input: [1,2,0]
Output: 3

Example 2:
Input: [3,4,-1,1]
Output: 2

Example 3:
Input: [7,8,9,11,12]
Output: 1

思路

1、標記法

如果 nums 的長度為 l,則結果肯定是在 1 ~ (l+1) 中的某個數。這是因為當 nums 包含了 1~l 的所有值時, 演算法結果最大,為 l+1。

因此只需要定義一個額外的陣列 list2,長度為 l,來標記對應的索引是否出現過正數即可。

具體步驟:

  • 定義一個額外的陣列 list2,長度為 l,元素都為 0
  • 遍歷 nums,每遇到一個小於等於 l 的元素值 a,便將 list2 中的a索引標記為1
  • 遍歷 list2, 找到第一個為 0 的位置,這個位置即為最小的缺失正整數

此方法的演算法複雜度為 O(l),空間複雜度為 O(l)。

2、改進版

標記法需要額外建立陣列,可以對其進行改進,不再額外建立一個新陣列,而是將 nums 當做新陣列。

注意:

  • 由於 nums 之前便有資料,因此在修改 nums 值時,需要將原來的值儲存下來,即與當前指標的值互換位置。
  • 將 nums 值修改為多少,可以保證這個索引出現過呢?不能是任何一個固定的數字,否則如果 nums 恰好為這個數字,則不知道應該不應該被標記。可以是一個固定的字串,這樣就可以與原有的數字們區分開來。

python實現

def firstMissingPositive(nums):
    """
    :type nums: List[int]
    :rtype: int
    如果 nums 的長度為 l,則結果肯定是在 1 ~ (l+1) 中的某個數,
    因為當 nums 包含了 1~l 的所有值時, 演算法結果最大,為 l+1。
    因此只需要定義一個額外的陣列 list2,長度為 l,元素都為 0。
    遍歷 nums,每遇到一個小於等於 l 的元素值 a,便將 list2 中的a索引標記為1。
    之後再遍歷一遍 list2, 找到第一個為 0 的位置,這個位置即為最小的缺失正整數。
    """
l = len(nums) if l == 0: return 1 list2 = [0] * l for i in nums: if i > 0 and i <= l: list2[i-1] = 1 for i in range(l): if list2[i] == 0: return i+1 return l+1 def firstMissingPositive2(nums): """ :type nums: List[int] :rtype: int 改進版。 """ l = len(nums) if l == 0: return 1 for i in range(l): tmp = nums[i] while tmp != 'a' and tmp > 0 and tmp <= l: nums[tmp-1], tmp = 'a', nums[tmp-1] for i in range(l): if nums[i] != 'a': return i+1 return l+1 if '__main__' == __name__: nums = [3,4,-1,1] print(firstMissingPositive2(nums))