Leetcode演算法——41、尋找缺失的正數
阿新 • • 發佈:2018-11-19
給定一個亂序的整數陣列,找到最小的缺失的正整數。
示例:
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))