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

【LeetCode热题100道笔记】缺失的第一个正数

题目描述

给你一个未排序的整数数组 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 <= 105
-231 <= nums[i] <= 231 - 1

思考一

先计算数组中的最大的数 maxNum,若最大数小于等于 0,则 maxNum = 1,否则为数组中最大的正整数。用哈希表存储数组中每个数,然后从[1,maxNum+1]中寻找数组不存在的最小正整数,用哈希表判断当前遍历的数是否存在。时间复杂度 O(n)O(n)O(n),空间复杂度 O(n)O(n)O(n)。由于题目要求使用常数级额外空间,因此当前实现不满足要求。

代码

/*** @param {number[]} nums* @return {number}*/
var firstMissingPositive = function(nums) {const set = new Set();let maxNum = 0;for (let num of nums) {maxNum = Math.max(maxNum, num);set.add(num);}if (maxNum < nums.length) {maxNum = nums.length;}for (let i = 1; i <= maxNum + 1; i++) {if (set.has(i)) continue;return i;}
};

思考二

要满足常数级常数级额外空间的要求,我们可以利用数组本身作为哈希表来标记元素的存在状态,核心思路是将值为x的元素放到索引x-1的位置上,然后检查第一个不匹配的索引 + 1 即为结果。

算法过程

  1. 置换阶段:遍历数组,将每个值为x1 ≤ x ≤ n)的元素交换到索引x-1的位置,确保"值"与"索引+1"对应
  2. 检查阶段:再次遍历数组,第一个不满足nums[i] === i+1的位置i,其i+1就是缺失的最小正整数
  3. 边界情况:如果所有位置都匹配,则缺失的是n+1

复杂度分析

  • 时间复杂度:O(n),每个元素最多被交换两次,整体仍是线性时间
  • 空间复杂度:O(1),仅使用常数级额外空间

代码

/*** @param {number[]} nums* @return {number}*/
var firstMissingPositive = function(nums) {const n = nums.length;// 第一步:将每个正数放到正确的位置上for (let i = 0; i < n; i++) {// 只有当当前数字是正数且在有效范围内,并且没有放在正确位置时才交换while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] !== nums[i]) {// 将nums[i]放到索引为nums[i]-1的位置[nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]];}}// 第二步:检查哪个位置没有对应的正数for (let i = 0; i < n; i++) {if (nums[i] !== i + 1) {return i + 1;}}// 所有位置都正确,则缺失的是n+1return n + 1;
};
http://www.xdnf.cn/news/19924.html

相关文章:

  • 【CouponHub项目开发】使用RocketMQ5.x实现延时修改优惠券状态,并通过使用模板方法模式重构消息队列发送功能
  • 3分钟快速了解ToDesk远程控制企业版的技术奥秘!
  • 为什么打印出来的 cJSON type 值和头文件定义的不一样?
  • git还原操作
  • ultralytics/nn/tasks.py源码学习笔记——核心函数parse_model
  • day2today3夏暮客的Python之路
  • 「逆向思维」的胜利:从“挤不上电梯”到“高效学习”的顶级心法
  • 2025年度GEO优化公司市场研究报告:技术驱动下的用户口碑洞察
  • Git的强软硬回退(三)
  • Docmost:面向现代团队的企业级Wiki
  • 鸿蒙:状态管理V2(V2装饰器的学习)
  • 超详细教程:一招一式教你将本地项目上传至GitHub
  • 【系统架构设计(13)】项目管理上:盈亏平衡分析与进度管理
  • SpringBoot 网络流量抓包与分析系统
  • 【RNN-LSTM-GRU】第一篇 序列建模基础:理解数据的“顺序”之力
  • Mac 使用 softhsm
  • 革新光纤锁模技术:《Light: Science Applications》报道纳米腔增强型可饱和吸收器
  • 质量管理里常见的缩写QA、QC、QE都是什么意思?
  • 彻底搞懂面向对象分析(OOA)
  • Linux内存管理章节一:深入浅出Linux内存管理:从物理内存到ARM32的用户与内核空间
  • 逻辑回归基础
  • .NET GcPDF V8.2 新版本:人工智能 PDF 处理
  • Spring Boot 根据配置优雅的决定实现类
  • Meshroom 2025.1.0安装及使用参数模板介绍:二维图片转三维重建
  • 因为对象装箱拆箱导致的空指针异常
  • C#强制类型转换(显示转换)和安全类型转换
  • 野火STM32Modbus主机读取寄存器/线圈失败(三)-尝试将存贮事件的地方改成数组(非必要解决方案)(附源码)
  • VBA中类的解读及应用第二十七讲:利用类完成查找的方案-5
  • SVT-AV1 svt_aom_motion_estimation_kernel 函数分析
  • 详细学习计划