41. First Missing Positive 缺失的第一个正数
Title
給你一個未排序的整數(shù)數(shù)組,請你找出其中沒有出現(xiàn)的最小的正整數(shù)。
示例 1:
輸入: [1,2,0]
輸出: 3
示例 2:
輸入: [3,4,-1,1]
輸出: 2
示例 3:
輸入: [7,8,9,11,12]
輸出: 1
提示:
你的算法的時間復(fù)雜度應(yīng)為O(n),并且只能使用常數(shù)級別的額外空間。
哈希表
Solve
我們可以將數(shù)組所有的數(shù)放入哈希表,隨后從1開始依次枚舉正整數(shù),并判斷其是否在哈希表中。
如果數(shù)組的長度為N,那么第一種做法的時間復(fù)雜度為O(N),空間復(fù)雜度為O(N)。
我們?yōu)槭裁匆褂霉1?#xff1f;
因?yàn)楣1硎且粋€可以支持快速查找的數(shù)據(jù)結(jié)構(gòu):給定一個元素,可以在O(1)的時間查找該元素是否在哈希表中。
因此,我們可以考慮將給定的數(shù)組設(shè)計成哈希表的【替代產(chǎn)品】。
實(shí)際上,對于長度為N的數(shù)組,其中沒有出現(xiàn)的最小正整數(shù)只能在[1, N+1]中,這樣以來,我們將所有在[1, N]范圍內(nèi)的數(shù)放入哈希表,也可以得到最終的答案,而給定的數(shù)組恰好長度為N,這讓我們有了一種將數(shù)組設(shè)計成哈希表的思路:
我們對數(shù)組進(jìn)行遍歷,對于遍歷到的數(shù) x,如果它在 [1, N] 的范圍內(nèi),那么就將數(shù)組中的第 x-1 個位置(注意:數(shù)組下標(biāo)從 0 開始)打上「標(biāo)記」。在遍歷結(jié)束之后,如果所有的位置都被打上了標(biāo)記,那么答案是 N+1,否則答案是最小的沒有打上標(biāo)記的位置加 1。
由于數(shù)組中的數(shù)沒有任何限制,因此這并不是一件容易的事情。但我們可以繼續(xù)利用上面的提到的性質(zhì):由于我們只在意 [1, N] 中的數(shù),因此我們可以先對數(shù)組進(jìn)行遍歷,把不在 [1, N] 范圍內(nèi)的數(shù)修改成任意一個大于 N 的數(shù)(例如 N+1)。這樣一來,數(shù)組中的所有數(shù)就都是正數(shù)了,因此我們就可以將「標(biāo)記」表示為「負(fù)號」。算法的流程如下:
Code
def firstMissingPositive(self, nums: List[int]) -> int:length = len(nums)for i in range(length):if nums[i] <= 0:nums[i] = length + 1for i in range(length):num = abs(nums[i])if num <= length:nums[num - 1] = -abs(nums[num - 1])for i in range(length):if nums[i] > 0:return i + 1return length + 1復(fù)雜度分析
時間復(fù)雜度:O(N),其中 N 是數(shù)組的長度。
空間復(fù)雜度:O(1)。
置換
Solve
將給定的數(shù)組「恢復(fù)」成下面的形式:如果數(shù)組中包含 x∈[1,N],那么恢復(fù)后,數(shù)組的第 x - 1 個元素為 x。
在恢復(fù)后,數(shù)組應(yīng)當(dāng)有[1, 2, …, N]的形式,但其中有若干個位置上的數(shù)是錯誤的,每一個錯誤的位置就代表了一個缺失的正數(shù)。
以題目中的示例二 [3, 4, -1, 1] 為例,恢復(fù)后的數(shù)組應(yīng)當(dāng)為 [1, -1, 3, 4],我們就可以知道缺失的數(shù)為 2。
那么我們?nèi)绾螌?shù)組進(jìn)行恢復(fù)呢?我們可以對數(shù)組進(jìn)行一次遍歷,對于遍歷到的數(shù)x=nums[i],如果 x∈[1,N],我們就知道 x 應(yīng)當(dāng)出現(xiàn)在數(shù)組中的 x - 1 的位置,因此交換nums[i] 和 nums[x?1],這樣 x 就出現(xiàn)在了正確的位置。
在完成交換后,新的 nums[i] 可能還在 [1,N] 的范圍內(nèi),我們需要繼續(xù)進(jìn)行交換操作,直到 x ? [1,N]。
注意到上面的方法可能會陷入死循環(huán)。如果 nums[i] 恰好與 nums[x?1] 相等,那么就會無限交換下去。
因此在這種情況下,x 本就已經(jīng)出現(xiàn)在了正確的位置,只是數(shù)組里面有多個 x 而已。因此我們就不需要進(jìn)行交換,而是開始遍歷下一個數(shù)。
由于每次的交換操作都會使得某一個數(shù)交換到正確的位置,因此交換的次數(shù)最多為 N,整個方法的時間復(fù)雜度為 O(N)。
Code
def firstMissingPositive(self, nums: List[int]) -> int:length = len(nums)for i in range(length):while 1 <= nums[i] <= length and nums[nums[i] - 1] != nums[i]:nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1]for i in range(length):if nums[i] != i + 1:return i + 1return length + 1復(fù)雜度分析
時間復(fù)雜度:O(N),其中 N 是數(shù)組的長度。
空間復(fù)雜度:O(1)。
總結(jié)
以上是生活随笔為你收集整理的41. First Missing Positive 缺失的第一个正数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面试题 02.01. 移除重复节点
- 下一篇: 209. Minimum Size Su