尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

hot100 缺失的第一个整数(41)

hot100 缺失的第一个整数(41)
📅 发布时间:2026/7/2 11:27:13

本题采用原地哈希(桶排序/基数排序思想)算法解决“缺失的第一个正数”问题。其核心本质是利用数组的索引下标作为天然的哈希表键值,通过不断的置换操作将符合范围的正整数强制归位到对应的物理位置。当前源码实现了在不占用额外内存空间的前提下进行数据的就位,最终走向是通过第二次线性扫描首个未就位的元素索引来精确锁定目标缺失值。

一、 问题本质与数据模型

对于长度为 n 的整数数组 nums,我们需要寻找没有出现的最小正整数。在处理该问题时,首先需要通过数学归纳确立结果的物理边界:

  • 最理想情况:如果数组包含从 1 到 n 的所有正整数[1, 2, 3, ..., n],那么缺失的第一个正整数必然为n + 1。

  • 非理想情况:如果数组中存在小于等于 0 的数、大于 n 的数、或是重复的数,根据抽屉原理(鸽巢原理),缺失的第一个正整数必然落在[1, n]的有效闭区间内。

由此可得,最终的答案必然位于[1, n + 1]之间。

这一数学边界直接决定了我们的数据模型:我们完全不需要理会小于等于 0 或大于 n 的数字,只需要聚焦于满足1 <= nums[i] <= n范围内的正整数,并设法验证它们是否全部就位。

在不被允许开辟额外哈希表的前提下,算法将原数组自身视为一个哈希表。对于任意满足范围的数值x,它在哈希表中的标准归宿就是数组的x - 1下标位置。即算法最终的目标是让数组尽可能满足:

nums[i] == i + 1

二、 算法演进对比

在解决动态正整数连续性判定问题时,原地哈希置换法在时空资源的利用效率上达成了最优解:

解法名称时间复杂度空间复杂度核心原理物理缺陷 / 瓶颈
标准双重循环排序O(n log n)O(1) 或 O(n)先对全数组进行快速排序或归并排序,随后线性扫描查找断层时间开销受限于排序上限,无法达到线性时间要求
辅助哈希集合去重O(n)O(n)将所有数字存入 HashSet,随后从 1 开始依次在集合中查询是否存在引入了与原数据等长的额外内存空间开销,违反常数空间约束
原地哈希置换(当前解法)O(n)O(1)利用数组下标作为哈希地址,通过不断交换元素让正确的数据归位需要在原数组内部进行直接的数据改写与位置置换

三、 原地哈希置换的核心控制逻辑

当前源码的卓越性在于通过一个内嵌的while循环实现了无额外空间的“数据自动归位”。其核心判定条件由三部分组成:

while (nums[i] >= 1 && nums[i] <= n && nums[nums[i] - 1] != nums[i])

1. 数值合法性过滤:nums[i] >= 1 && nums[i] <= n

只有当前元素位于[1, n]区间内时,它才拥有在数组中被归位的资格。任何负数、0 以及超出数组长度的大整数都无法匹配任何合法的数组下标,直接跳过。

2. 目标冲突判定:nums[nums[i] - 1] != nums[i]

这是防止算法陷入死循环的核心防护网。

  • 设当前位置的数值为x = nums[i],它本应该待的地方是目标索引j = x - 1。

  • 只有当目标位置上的数值nums[j]还不等于x时(即nums[nums[i] - 1] != nums[i]),才需要执行交换。

  • 逻辑证明:如果满足nums[j] == x,说明该数字在目标位置上已经存在(遇到了重复元素)。此时如果继续交换,当前位置的值不会发生改变,while循环将永远无法退出。

3. 为什么必须使用while而不是if?

当我们将nums[i]交换到它应该去的目的地nums[j]后,原本待在nums[j]的那个未知元素被换到了当前位置i。这个换过来的新元素同样可能是个合法的、需要归位的数字。因此必须使用while循环不断对当前位置i上的新元素进行重复判定与置换,直到换过来的元素是一个非法值或是一个已经正确就位的元素为止。

四、 算法执行状态机步进示例

以输入数据nums = [3, 4, -1, 1]为例(此时数组长度n = 4),外层循环变量i推进时的内部置换状态演进过程如下表所示:

步骤外层索引 i当前元素 nums[i]满足 while 条件与置换过程数组内部实时元素状态物理意义说明
初始---[3, 4, -1, 1]原始无序状态
103

满足。目标索引j = 3-1 = 2。

与nums[2](-1) 互换。

[-1, 4, 3, 1]数字 3 成功归位到下标 2
20-1-1 < 1,不满足条件,跳出 while。[-1, 4, 3, 1]当前位置为无效值,指针右移
314

满足。目标索引j = 4-1 = 3。

与nums[3](1) 互换。

[-1, 1, 3, 4]数字 4 成功归位到下标 3
411

满足。目标索引j = 1-1 = 0。

与nums[0](-1) 互换。

[1, -1, 3, 4]数字 1 成功归位到下标 0
51-1-1 < 1,不满足条件,跳出 while。[1, -1, 3, 4]当前位置为无效值,指针右移
623nums[2] == 2+1,已正确就位,跳过。[1, -1, 3, 4]指针右移
734nums[3] == 3+1,已正确就位,跳过。[1, -1, 3, 4]第一轮置换完全结束
扫描从 0 到 3-检查到nums[1] = -1 != 2触发return i + 1输出结果:2

五、源码实现

class Solution { public int firstMissingPositive(int[] nums) { // 边界安全检查 if (nums == null || nums.length == 0) { return 1; } int n = nums.length; // 步骤 1:原地哈希置换,尝试将每个满足 [1, n] 范围的数字 x 放到对应的下标 x - 1 上 for (int i = 0; i < n; i++) { // 使用 while 循环,持续对换到当前位置 i 的新元素进行就位处理 // 条件包含:数值在合法区间内,且目标位置上的数值与当前数值不相等(防重复死循环) while (nums[i] >= 1 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) { // 计算目标归宿索引 int j = nums[i] - 1; // 进行原地元素对调 int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } } // 步骤 2:再次扫描调整后的数组,寻找第一个没有正确就位的物理位置 for (int i = 0; i < n; i++) { // 如果当前位置的值不等于 索引 + 1,说明该正整数缺失 if (nums[i] != i + 1) { return i + 1; } } // 步骤 3:如果数组中 [1, n] 的所有正整数都正确就位了,则缺失的必然是 n + 1 return n + 1; } }

六、 复杂度极限分析

1. 时间复杂度 O(n)

  • 精确摊还分析:虽然代码的结构上表现为for循环内部嵌套了一个while循环,但我们不能简单地将其评估为平方阶。从物理置换的本质来看,每一次成功的swap操作,都必然会将至少一个原本错位的数字送入到它长久正确的最终位置(即满足nums[j] == j + 1)。

  • 结论:一旦一个元素正确就位,它就绝不会再次被挪动。由于数组中总共只有 n 个元素,整个算法生命周期里发生的总交换次数绝对不会超过n - 1次。因此,while循环的平均摊还时间开销为常数阶 O(1),结合随后的第二次线性扫描,综合总时间复杂度稳定在 O(n)。

2. 空间复杂度 O(1)

  • 分析:算法所有的元素移位、调配与对调逻辑全部直接施加在传入的原始nums数组内存块上展开(原地算法)。执行期间,除独立声明了n,i,j,temp等有限个用于控制迭代和辅助对调的基础类型整型变量外,没有申请任何与输入规模相关的外部数据结构。

  • 结论:额外内存的消耗固定为常数阶,空间复杂度为严格的 O(1)。

相关新闻

  • Linux 【01- ping命令超详细教程】
  • how to 梳理 this porject 结构 for quick knowing the 干什么的 which file
  • 智能体认知架构中的长期记忆与聊天摘要记忆管理系统研究报告

最新新闻

  • 如何专业测试鼠标性能:开源工具实用指南
  • 深蓝词库转换:终极跨平台输入法词库迁移解决方案深度解析
  • IIM-42652与STM32F411RE实现6DoF姿态解算实战
  • Python 行情数据留痕:symbol、timestamp、字段和 raw_snapshot 怎么记录
  • Caddy服务器加密ClientHello(ECH)配置实战:原理、部署与排障指南
  • 【Springboot毕设全套源码+文档】基于springboot线上超市购物管理系统的设计与实现(丰富项目+远程调试+讲解+定制)

日新闻

  • Python Playwright录制功能:从零到一构建自动化测试脚本
  • 如何用开源工具永久保存你心爱的小说:novel-downloader全攻略
  • In-Context Learning不是教知识,而是模式对齐:从5个示例到100个工业级样本的真相

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号