当前位置: 首页 > news >正文

【LeetCode刷题】缺失的第一个正数

给你一个未排序的整数数组nums,请你找出其中没有出现的最小的正整数。

请你实现时间复杂度为O(n)并且只使用常数级别额外空间的解决方案。

示例 1:

输入:nums = [1,2,0]输出:3解释:范围 [1,2] 中的数字都在数组中。

示例 2:

输入:nums = [3,4,-1,1]输出:2解释:1 在数组中,但 2 没有。

示例 3:

输入:nums = [7,8,9,11,12]输出:1解释:最小的正数 1 没有出现。

提示:

  • 1 <= nums.length <=
  • -231 <= nums[i] <=

解题思路

要在 O (n) 时间复杂度和常数级额外空间内解决问题,核心思路是原地哈希(标记)

  1. 范围确定:缺失的最小正整数一定在[1, n+1]范围内(n 为数组长度)。例如数组长度为 3,若 1、2、3 都存在则返回 4,否则返回缺失的最小数。
  2. 过滤无效值:将数组中所有≤0 或 > n 的数替换为n+1(这些数不可能是目标,替换后不干扰后续标记)。
  3. 标记存在的数:遍历数组,对每个元素x(取绝对值),若x ≤ n,则将数组第x-1位标记为负数(表示x这个数存在)。
  4. 查找缺失值:遍历数组,第一个正数的位置i+1就是缺失的最小正整数;若全为负数,说明 1~n 都存在,返回n+1

示例验证

示例 1:输入nums = [1,2,0]
  1. 过滤无效值:0 替换为 4 →[1,2,4]
  2. 标记存在的数:
    • x=1 → nums[0] = -1;
    • x=2 → nums[1] = -2;
    • x=4(>3)→ 不处理;数组变为[-1,-2,4]
  3. 遍历找正数:索引 2 是第一个正数,返回2+1=3(符合预期)。
示例 2:输入nums = [3,4,-1,1]
  1. 过滤无效值:-1 替换为 5,4 替换为 5 →[3,5,5,1]
  2. 标记存在的数:
    • x=3 → nums[2] = -5;
    • x=5(>4)→ 不处理;
    • x=5(>4)→ 不处理;
    • x=1 → nums [0] = -3;数组变为[-3,5,-5,1]
  3. 遍历找正数:索引 1 是第一个正数,返回1+1=2(符合预期)。
示例 3:输入nums = [7,8,9,11,12]
  1. 过滤无效值:所有数 > 5,替换为 6 →[6,6,6,6,6]
  2. 标记存在的数:所有 x=6(>5)→ 不处理,数组仍为[6,6,6,6,6]
  3. 遍历找正数:索引 0 是第一个正数,返回0+1=1(符合预期)。

核心优势

  • 时间复杂度 O (n):仅三次线性遍历,无嵌套操作;
  • 空间复杂度 O (1):仅使用常数级临时变量,原地修改数组;
  • 鲁棒性:处理了负数、重复值、超大数等边界场景,适配题目 10⁵级别的数组长度。

Python代码:

from typing import List class Solution: def firstMissingPositive(self, nums: List[int]) -> int: n = len(nums) # 过滤无效值 for i in range(n): if nums[i] <= 0 or nums[i] > n: nums[i] = n + 1 # 标记存在的数 for i in range(n): x = abs(nums[i]) if x <= n: nums[x - 1] = -abs(nums[x - 1]) # 查找缺失值 for i in range(n): if nums[i] > 0: return i + 1 return n + 1 # 测试用例 if __name__ == "__main__": solution = Solution() # 示例1 nums1 = [1,2,0] print(f"示例1输入: {nums1}") print(f"示例1输出: {solution.firstMissingPositive(nums1)}") # 示例2 nums2 = [3,4,-1,1] print(f"示例2输入: {nums2}") print(f"示例2输出: {solution.firstMissingPositive(nums2)}") # 示例3 nums3 = [7,8,9,11,12] print(f"示例3输入: {nums3}") print(f"示例3输出: {solution.firstMissingPositive(nums3)}") # 边界用例:1~n都存在 nums4 = [1,2,3,4] print(f"示例4输入: {nums4}") print(f"示例4输出: {solution.firstMissingPositive(nums4)}") # 边界用例:空值/重复值 nums5 = [2,2,2] print(f"示例5输入: {nums5}") print(f"示例5输出: {solution.firstMissingPositive(nums5)}")

LeetCode提交代码:

from typing import List class Solution: def firstMissingPositive(self, nums: List[int]) -> int: n = len(nums) # 步骤1:过滤无效值(≤0 或 >n的数替换为n+1,不干扰后续标记) for i in range(n): if nums[i] <= 0 or nums[i] > n: nums[i] = n + 1 # 步骤2:标记存在的正整数(用负数标记,表示对应数存在) for i in range(n): x = abs(nums[i]) # 取绝对值,避免已标记的负数干扰 if x <= n: # 仅处理1~n范围内的数 nums[x - 1] = -abs(nums[x - 1]) # 标记为负数(重复标记不影响) # 步骤3:查找第一个未标记的位置(正数),返回i+1 for i in range(n): if nums[i] > 0: return i + 1 # 所有1~n都存在,返回n+1 return n + 1

程序运行结果如下:

示例1输入: [1, 2, 0] 示例1输出: 3 示例2输入: [3, 4, -1, 1] 示例2输出: 2 示例3输入: [7, 8, 9, 11, 12] 示例3输出: 1 示例4输入: [1, 2, 3, 4] 示例4输出: 5 示例5输入: [2, 2, 2] 示例5输出: 1

总结

本文提出了一种在O(n)时间复杂度和常数空间内寻找数组中缺失最小正整数的算法。核心思路是通过原地哈希标记:首先过滤无效值(≤0或>n的数),然后利用数组索引标记存在的正整数(1~n),最后扫描数组找到第一个未被标记的位置。该方法高效处理了各种边界情况(负数、重复值、超大数等),并通过三个线性遍历实现最优复杂度。Python实现验证了算法的正确性,适用于LeetCode等编程挑战。

http://www.jsqmd.com/news/79673/

相关文章:

  • 突破AI推理天花板:GenSelect与TIR技术如何重塑大模型决策能力
  • 国内大模型部署难题突破:轻量级模型Magistral-Small-2509实现低资源环境高效运行
  • Z-image LoRA 训练整合包下载与使用教程(详细图文教程)
  • OTOFIX D1 PRO One-Year Online Update Subscription for European/American Vehicles
  • Dubbo学习(二):深入 RPC
  • League Akari:8大实用功能快速提升你的英雄联盟游戏体验
  • Dubbo学习(三):深入 Remoting
  • 神经网络中有超参数和自学习参数吗?
  • Day23 回归问题与置信区间
  • AI设计新突破:QWEN溶图LoRA模型助力品牌视觉创作升级
  • 大模型教我成为大模型算法工程师之day8: 优化器与训练技巧
  • Java毕设项目:基于springboot成都旅游网四季成都、特色文化(源码+文档,讲解、调试运行,定制等)
  • League Akari:6个实用功能让你告别繁琐操作,轻松上分
  • api vs jsp 绑定风格
  • 理解 Proxy 原理及如何拦截 Map、Set 等集合方法调用实现自定义拦截和日志——含示例代码解析
  • Java毕设项目:基于springboot厨具厂产品在线销售系统设计与实现小程序(源码+文档,讲解、调试运行,定制等)
  • Java毕设项目:基于springboot二手商品网站(源码+文档,讲解、调试运行,定制等)
  • 详解 Gitee/GitHub 中 HTTPS/SSH 方式数据库仓库创建与本地连接
  • 第五十七篇-ComfyUI+V100-32G+安装SD1.5
  • 突破实时视频生成瓶颈:Krea Realtime 14B模型革新文本到视频技术
  • systemd-resolved.service实验实战3
  • 哔哩下载姬:5个实用技巧让你的B站视频下载效率翻倍
  • Windows右键菜单终极优化指南:从卡顿到流畅的深度解析
  • 腾讯优图实验室开源Youtu-Embedding文本表示模型,赋能企业级AI应用创新
  • SAM3在医疗影像里“指鹿为马”?MedSAM3来了——文本一句话,精准分割病灶
  • Java毕设项目:基于SpringBoot网上超市的设计与实现基于springboot超市在线销售系统的设计与实现(源码+文档,讲解、调试运行,定制等)
  • 小学娃近视防控不费妈!这款眼调节训练灯,学习护眼一步到位
  • 无人机看地面小目标总“眼瞎”?MambaRefine-YOLO来救场:双模态融合+高效检测,精度直接拉满!
  • QDialog-基础讲解
  • 【异常】豆包TTS语音合成常见报错及SSML代码实现解决方案