力扣(LeetCode)100题:41.缺失的第一个正数

41.缺失的第一个正数

我的题解:排序+遍历

python 复制代码
class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        nums.sort()
        j=1
        for i in range(len(nums)-1):
            if nums[i]<=0 or nums[i]==nums[i+1]:
                continue
            if nums[i]==j:
                j+=1
            else:
                return j
        if nums[len(nums)-1]==j:
            j+=1
        else:
            return j
        return j

官方题解

一、哈希表

✅ 解法核心思想:原地标记法(利用数组下标作为"哈希表")

我们将数组本身当作一个隐式的哈希表:

  • 如果数字 x(1 ≤ x ≤ n)存在,则让 nums[x - 1] 变为负数(作为标记)
  • 最后遍历数组,第一个仍为正数的位置 i,说明 i+1 没有出现 → 即答案

🔍 逐行注释与解释

复制代码
class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        n = len(nums)
        
        # 第一步:把所有非正数(≤0)替换为一个"无关"的大数(n+1)
        # 因为我们只关心 1 到 n 的正整数(答案一定在 [1, n+1] 中)
        for i in range(n):
            if nums[i] <= 0:
                nums[i] = n + 1
        
        # 第二步:遍历数组,对每个在 [1, n] 范围内的数 x,
        # 将 nums[x - 1] 标记为负数(表示 x 已出现)
        for i in range(n):
            num = abs(nums[i])          # 取绝对值,因为可能已被标记为负
            if num <= n:                # 只处理 1 ~ n 的数
                nums[num - 1] = -abs(nums[num - 1])  # 标记位置 num-1 为负
        
        # 第三步:再次遍历,找第一个仍为正数的位置 i
        # 说明数字 i+1 没有出现过
        for i in range(n):
            if nums[i] > 0:
                return i + 1
        
        # 如果 1~n 都出现了,那么答案就是 n+1
        return n + 1

📌 为什么答案一定在 [1, n+1]

  • 数组长度为 n
  • 最理想情况:nums = [1, 2, 3, ..., n] → 缺失的是 n+1
  • 其他情况:至少有一个 1~n 中的数缺失 → 答案 ∈ [1, n]
  • 所以 答案 ∈ [1, n+1],无需考虑更大的数!

因此,我们可以安全地忽略所有 > n≤ 0 的数。


🧪 举例说明

示例 1:
复制代码
nums = [3, 4, -1, 1]
n = 4

Step 1 : 替换非正数

[3, 4, 5, 1] (-1 → 5)

Step 2: 标记出现的数

  • i=0: num=3 → 标记 index=2 → [3, 4, -5, 1]
  • i=1: num=4 → 标记 index=3 → [3, 4, -5, -1]
  • i=2: num=5(>4)→ 忽略
  • i=3: num=1 → 标记 index=0 → [-3, 4, -5, -1]

Step 3 : 找第一个正数

→ index=1 是正数(4)→ 返回 1+1 = 2

示例 2:
复制代码
nums = [1, 2, 0]
n = 3

→ Step1: [1,2,4]

→ Step2: 标记 1→index0, 2→index1, 4忽略 → [-1,-2,4]

→ Step3: index2 为正 → 返回 3

示例 3:
复制代码
nums = [1, 2, 3]
n = 3

→ 全部标记为负:[-1,-2,-3]

→ 没有正数 → 返回 4

二、置换

✅ 核心思想(原地置换 / Cyclic Sort)

数组长度为 n,则答案必定在 [1, n+1] 范围内。

若数字 x(满足 1 ≤ x ≤ n)存在,则应将其放到下标 x - 1 的位置上。

最终遍历数组,第一个不满足 nums[i] == i + 1 的位置,其 i + 1 即为缺失的最小正整数。


🧩 代码解析

复制代码
class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        n = len(nums)
        
        # 将每个合法正整数(1~n)放到它"应该在"的位置:nums[x-1] = x
        for i in range(n):
            while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:
                # 交换:把 nums[i] 放到正确位置,同时把原来那里的数换过来
                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
        
        # 若 1~n 都在正确位置,则缺失的是 n+1
        return n + 1
相关推荐
2503_946971865 小时前
【BruteForce/Pruning】2026年度物理层暴力破解与神经网络剪枝基准索引 (Benchmark Index)
人工智能·神经网络·算法·数据集·剪枝·网络架构·系统运维
R&ain5 小时前
C++的内联函数
c++·算法
zhmc5 小时前
常用周期函数的傅里叶级数
人工智能·算法
漫随流水6 小时前
leetcode算法(111.二叉树的最小深度)
数据结构·算法·leetcode·二叉树
じ☆冷颜〃13 小时前
黎曼几何驱动的算法与系统设计:理论、实践与跨领域应用
笔记·python·深度学习·网络协议·算法·机器学习
数据大魔方13 小时前
【期货量化实战】日内动量策略:顺势而为的短线交易法(Python源码)
开发语言·数据库·python·mysql·算法·github·程序员创富
POLITE313 小时前
Leetcode 23. 合并 K 个升序链表 (Day 12)
算法·leetcode·链表
楚来客14 小时前
AI基础概念之八:Transformer算法通俗解析
人工智能·算法·transformer
Echo_NGC223714 小时前
【神经视频编解码NVC】传统神经视频编解码完全指南:从零读懂 AI 视频压缩的基石
人工智能·深度学习·算法·机器学习·视频编解码
会员果汁14 小时前
leetcode-动态规划-买卖股票
算法·leetcode·动态规划