↓快轉到主要內容
  1. LeetCode/

LeetCode 41: First Missing Positive

·2 分鐘· ·
LeetCode Hard Hash-Table Array
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: hard 第一次嘗試:2026-01-31

  • 提交紀錄:Wrong Answer ×4 → Accepted ×2;2026-07-07 重寫:Accepted ×2 → Wrong Answer → Accepted

解題思路
#

長度 n 的陣列最多放下 1..n,所以答案一定在 1..n + 1。要 O(1) 額外空間,就把陣列本身當雜湊表(Hash Table 模板二):

  1. <= 0 的值不可能影響答案,換成 n + 1。
  2. 對每個值 v(取絕對值,因為可能已經被標記成負的),如果 1 <= v <= n,把 nums[v - 1] 變成負的,代表「v 出現過」。
  3. 第一個還是正的位置 i,答案就是 i + 1;全部都是負的,答案是 n + 1。

我的嘗試
#

前四版都把 <= 0 的值換成 0,問題就出在 0:

版本問題
第一版全部都在時回傳 n,應該是 n + 1。例如 [1]:答案 2,回傳 1
第二版改成回傳「最大值 + 1」,但最大值是在換成 0 之前算的。[-1]:答案 1,回傳 0
第三版最大值移到之後算,但位置上的 0 不是正的,被當成「出現過」。[0, 3]:答案 1,回傳 2
第四版改成檢查 >= 0,但 0 加負號還是 0,真的出現過的值也標不上去。[0, 1]:答案 2,回傳 1
AC換成 n + 1,負號就能正常標記

半年後重寫時又漏了最後的 return,[1] 回傳 None。

正確解法
#

class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        n = len(nums)
        for i in range(n):
            if nums[i] <= 0:
                nums[i] = n + 1                    # 不能用 0:0 沒辦法加負號
        for x in nums:
            v = abs(x)
            if v <= n:
                nums[v - 1] = -abs(nums[v - 1])    # 標記 v 出現過
        for i in range(n):
            if nums[i] > 0:
                return i + 1
        return n + 1

複雜度
#

時間 O(n),額外空間 O(1)。

要特別避免的錯誤
#

  • 「不可能的值」不能用 0,負號標記不了。
  • 讀值時要取絕對值,它可能已經被標記成負的。
  • 1..n 全部都在時答案是 n + 1。

面試口說整理
#

答案一定在 1 到 n + 1。我先把非正數換成 n + 1,再用 nums[v - 1] 的負號記錄 v 有沒有出現,讀值時記得取絕對值。最後第一個還是正的位置就是答案,都負的話是 n + 1。時間 O(n)、額外空間 O(1)。

相關文章

LeetCode 2122: Recover the Original Array
·2 分鐘
LeetCode Hard Two-Pointers Sorting Hash-Table Enumeration Array
LeetCode 2122 解題筆記:最小的數一定在 lower,枚舉它的配對決定 k;排序後用兩個指針把每個最小的未配對數配給 +2k 的數
LeetCode 2009: Minimum Number of Operations to Make Array Continuous
·1 分鐘
LeetCode Hard Sliding-Window Hash-Table Binary-Search Array
LeetCode 2009 解題筆記:最後的陣列是長度 n 的連續整數;去重排序後,用滑動視窗找值域寬度 <= n - 1 的最多不同值,其他都要改
LeetCode 952: Largest Component Size by Common Factor
·2 分鐘
LeetCode Hard Math Number-Theory Union-Find Hash-Table Array
LeetCode 952 解題筆記:有共同因數 ⇔ 有共同的質因數;把每個數分解質因數,同一個質因數的 index 用 Union-Find 合併,不用兩兩算 GCD
LeetCode 992: Subarrays with K Different Integers
·1 分鐘
LeetCode Hard Sliding-Window Hash-Table Counting Array
LeetCode 992 解題筆記:「剛好 k 種」=「最多 k 種」−「最多 k - 1 種」,「最多」型的計數視窗每個右端加 right - left + 1
LeetCode 442: Find All Duplicates in an Array
·1 分鐘
LeetCode Medium Hash-Table Array
LeetCode 442 解題筆記:值在 1..n,用 nums[v-1] 的負號記錄 v 出現過;第二次遇到時它已經是負的
LeetCode 1793: Maximum Score of a Good Subarray
·1 分鐘
LeetCode Hard Two-Pointers Greedy Binary-Search Array Monotonic-Stack
LeetCode 1793 解題筆記:從 k 往兩邊擴張,每次往鄰居比較大的那一邊走,讓每個長度的最小值盡量大;到邊界時只能往另一邊