[leetcode 41]缺失的第一個正數(Python)

題目描述

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

你的算法的時間複雜度應爲O(n),並且只能使用常數級別的額外空間。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/first-missing-positive


結題思路

來源於官方題解:

哈希表:

哈希表是一個可以支持快速查找的數據結構,給定一個元素,我們可以在O(1)的時間查找該元素是否在哈希表中。爲了滿足題目要求的時空複雜度,可以考慮將給定的數組設計成哈希表的替代品。

對於一個長度爲N的數組,沒有出現的最小正整數一定在[1, N+1]中。如果[1, N]都出現了,答案就是N+1,否則就是[1, N]中沒有出現的最小正整數。所以,只要將所有在[1, N]範圍內的數放入哈希表就可以找到答案,而輸入的數組長度就是N,所以可以加以利用。

  • 算法思路:
    對數組遍歷,對於遍歷到的數x,如果在[1, N]範圍內,就將數組的第x-1個位置打上標記,遍歷結束後如果所有位置都打上了標記則答案就是N+1,否則就是沒打標記的最小的位置加1。
    至於如何打標記,由於數組中的數沒有限制,但我們只在意[1, N]範圍的數,所以可以先遍歷數組,把不再該範圍內的數改成任意一個大於N的數(比如N+1)。這樣數組中的數都是正數了,就可以將負號作爲標記。

- 算法流程如下:

  1. 將數組中所有<=0的數改成N+1;
  2. 遍歷數組中的每個數,因爲可能是重複的數,所以可能已經被打了標記。如果|x|∈[1, N],那麼給數組中第|x|-1個位置的數加上負號,注意不要重複添加負號(所以只要先取絕對值再加負號就可以)。
  3. 在遍歷數組找到第一個不爲負數的數,返回這個位置+1;否則每一個數都爲負,返回N+1。

- 複雜度分析

  1. 時間複雜度:O(N)
  2. 空間複雜度:O(1)

換位置:

將給定的數組恢復成如下形式:

如果數組中包含x∈[1, N],恢復後的第x-1的元素爲x。

恢復後數組應該有[1, 2, 3, …, N]的形式,但是其中有的位置上的數是錯誤的,正代表着缺失的正數。

比如:[3, 4, -1, 1],置換後的數組爲[1, -1, 3, 4],所以缺失的數是2。

  • 置換過程如下:
    遍歷數組,對於x=nums[i],如果x∈[1, N],則x應該出現在數組中的 x-1 的位置。完成交換後,新的nums[i]可能還在[1, N]範圍內,需要繼續進行交換操作直到x不屬於[1, N]。
    爲了避免死循環,如果nums[i] = x = nums[x-1],則x已經出現在了正確位置,則跳出循環遍歷下一個數。
    每次交換都會使一個數被交換到正確位置,故交換次數最多爲N,算法的時間複雜度爲O(N)。

代碼實現

哈希表:

def firstMissingPositive(self, nums):
        n = len(nums)
        for i in range(n):
            if nums[i] <= 0:
                nums[i] = n+1

        for i in range(n):
            tmp = abs(nums[i])
            if tmp < n+1:
                nums[tmp-1] = -abs(nums[tmp-1])

        for i in range(n):
            if nums[i] > 0:
                return i+1
        
        return n+1

換位置:

class Solution(object):
    def firstMissingPositive(self, nums):
        n = len(nums)
        for i in range(n):
            while 1 <= nums[i] <= n and nums[i] != nums[nums[i]-1]:
                nums[nums[i]-1], nums[i] =  nums[i], nums[nums[i]-1]
        for i in range(n):
            if nums[i] != i+1:
                return i+1
        return n+1  

Tips

  1. Python裏兩元素置換可以直接: a,b=b,a。
  2. 哈希表非常適合快速查找元素。

Author:ChierAuthor: Chier

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