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

力扣hot100:缺失的第一个正数(哈希思想)(41)

题目描述:
解题思路

核心思路是通过原地标记实现空间复杂度 O(1)。缺失的最小正整数一定在 [1, n+1] 范围内(n 是数组长度),因此只需关注这个范围内的数。分三步操作:

  1. 预处理非正数:将所有非正数(负数和零)替换为 n+1,避免干扰后续标记。
  2. 标记出现过的数:遍历数组,对每个值 x,若 x ∈ [1, n],将位置 x-1 的值标记为负数(表示 x 出现过)。
  3. 查找缺失数:再次遍历数组,第一个正数所在位置 i 表示 i+1 是缺失的最小正整数;若全为负数,则缺失的是 n+1
代码实现
class Solution {public int firstMissingPositive(int[] nums) {int n = nums.length;// 步骤1:将所有非正数替换为 n+1for (int i = 0; i < n; i++) {if (nums[i] <= 0) {nums[i] = n + 1;}}// 步骤2:标记出现过的数for (int i = 0; i < n; i++) {int num = Math.abs(nums[i]); // 取绝对值(可能已被标记为负)if (num <= n) {// 将 num-1 位置的值置为负数(表示 num 出现过)nums[num - 1] = -Math.abs(nums[num - 1]); }}// 步骤3:查找第一个正数位置for (int i = 0; i < n; i++) {if (nums[i] > 0) {return i + 1; // 当前位置未标记,i+1 即为缺失的数}}return n + 1; // 所有位置均被标记,缺失 n+1}
}

关键步骤解析
  1. 预处理非正数
   for (int i = 0; i < n; i++) {if (nums[i] <= 0) {nums[i] = n + 1; // 替换为超出范围的值}}

  • 非正数不影响结果,替换为 n+1 后,数组中只剩正数,便于后续标记。
  1. 负数标记法
   int num = Math.abs(nums[i]); // 获取原始值(可能已被其他操作标记为负)if (num <= n) {nums[num - 1] = -Math.abs(nums[num - 1]); // 确保标记为负数}

  • 绝对值的作用:若 nums[i] 已被标记为负,Math.abs 能还原其原始值。
  • 负号标记:通过将 nums[num-1] 设为负数,表示 num 出现过(如 num=3 则标记索引 2)。
  • 避免重复标记Math.abs(...) 确保即使位置已被标记,也不会因二次取负变正。
  1. 查找缺失数
   for (int i = 0; i < n; i++) {if (nums[i] > 0) {return i + 1; // 位置 i 未标记,说明 i+1 缺失}}return n + 1;

  • 若位置 i 的值为正,说明 i+1 未出现过(未被标记)。
复杂度分析
  • 时间复杂度:三次遍历,总计 O(n)。
  • 空间复杂度:O(1),仅用常量空间。
示例推演

nums = [3, 4, -1, 1] 为例:

  1. 预处理:替换非正数 -1 → 5,数组变为 [3, 4, 5, 1]
  2. 标记出现过的数
    • 3 → 标记索引 2[3, 4, -5, 1]
    • 4 → 标记索引 3[3, 4, -5, -1]
    • 5 → 跳过(超出范围)
    • 1 → 标记索引 0[-3, 4, -5, -1]
  3. 查找缺失数:索引 1 的值为正数 4 → 缺失数 1+1=2
总结

通过原地利用数组下标进行标记,避免了额外空间开销。核心技巧是:

  1. 预处理排除干扰值。
  2. 用负号标记出现过的数(注意重复标记问题)。
  3. 通过正数位置定位缺失值。

此方法简洁高效,充分体现了数组下标与值之间的映射关系,是解决此类问题的经典思路。


文章转载自:

http://4MqBgBOg.hkpyp.cn
http://Tg8i3jRg.hkpyp.cn
http://jekOnzWd.hkpyp.cn
http://LUI7CClU.hkpyp.cn
http://tbmKn1he.hkpyp.cn
http://N2dXjR2h.hkpyp.cn
http://u17kgtNT.hkpyp.cn
http://pZKZEaHb.hkpyp.cn
http://TYlIn4Ne.hkpyp.cn
http://59xRxvsT.hkpyp.cn
http://0lOboLqv.hkpyp.cn
http://YociQgYh.hkpyp.cn
http://Y1E3FP7t.hkpyp.cn
http://iwCxWNcU.hkpyp.cn
http://n3h8HEJJ.hkpyp.cn
http://x0iGuOdK.hkpyp.cn
http://KrdIQfae.hkpyp.cn
http://L2j5BvoY.hkpyp.cn
http://vgDsyXmS.hkpyp.cn
http://zvMlABsY.hkpyp.cn
http://NA1aKMGy.hkpyp.cn
http://IahliDFu.hkpyp.cn
http://6jnH7w9n.hkpyp.cn
http://yGveffUK.hkpyp.cn
http://3HBuJInV.hkpyp.cn
http://kZ5j632a.hkpyp.cn
http://Qx0YtUGp.hkpyp.cn
http://3i4Gbjl9.hkpyp.cn
http://yo33fzUQ.hkpyp.cn
http://Ap6mj9zq.hkpyp.cn
http://www.dtcms.com/a/363621.html

相关文章:

  • 领导层必看:Curtain e-locker为您轻松管理“文件外发“
  • MySQL 多表查询方法
  • day42-单片机
  • 基于3dtitle模型无法双面渲染问题
  • 友思特案例 | 食品行业视觉检测案例集锦(三)
  • 实验4-HTTP协议的运行过程
  • 失业落伍前端, 尝试了一个月 ai 协助编程的真实感受
  • Vscode + docker + qt 网络监听小工具
  • 25.9.2_CTF_reverse_TEA算法
  • 项目解析:技术实现与面试高频问题
  • 交叉熵损失函数
  • 一文读懂 Python 【循环语句】:从基础到实战,效率提升指南
  • 零构建的快感!dagger.js 与 React Hooks 实现对比,谁更优雅?
  • 餐饮、跑腿、零售多场景下的同城外卖系统源码扩展方案
  • 基于高德地图实现后端传来两点坐标计算两点距离并显示
  • JDK16安装步骤及下载(附小白详细教程)
  • 【Spring Cloud微服务】9.一站式掌握 Seata:架构设计与 AT、TCC、Saga、XA 模式选型指南
  • Javascript》》JS》》ES6》 Map、Set、WeakSet、WeakMap
  • Java 技术支撑 AI 系统落地:从模型部署到安全合规的企业级解决方案(一)
  • SQL分类详解:掌握DQL、DML、DDL等数据库语言类型
  • Java-Spring入门指南(二)利用IDEA手把手教你如何创建第一个Spring系统
  • Python学习-day4
  • win32diskimager强行缩减TF卡镜像制作尺寸的方法
  • Zynq中级开发七项必修课-第四课:S_AXI_HP0 高速端口访问 DDR
  • 整理期初数据用到的EXCEL里面的函数操作
  • 2026届长亭科技秋招正式开始
  • 炫酷JavaScript鼠标跟随特效
  • Nano Banana 新玩法超惊艳!附教程案例提示词!
  • CMake构建学习笔记23-SQLite库的构建
  • SQL Server 数据库创建与用户权限绑定