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

一天一道算法题(8):原地哈希的思路与实现解析

LeetCode 41:缺失的第一个正数(最优解详解)

在LeetCode的算法题中,41. 缺失的第一个正数 是一道典型的“困难”级别题目。它的难点不在于思路有多复杂,而在于其对算法效率的严格要求:时间复杂度 O(n),空间复杂度 O(1)

本文将带你一步步剖析,如何满足这两个苛刻的条件,找出数组中缺失的最小正整数。

文章目录

    • LeetCode 41:缺失的第一个正数(最优解详解)
      • 题目回顾
      • 思路分析:为什么常规解法不行?
      • 核心思想:原地哈希(索引即键)
      • 算法步骤详解
        • 第一步:预处理(处理非正数)
        • 第二步:交换元素到正确位置
        • 第三步:扫描并返回结果
      • 代码实现(Golang)
      • 复杂度分析
      • 总结

题目回顾

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

示例:

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

思路分析:为什么常规解法不行?

看到题目,我们很容易想到两种最直接的解法,但它们的性能都不达标:

  1. 排序法:先排序,再遍历。时间复杂度为O(n log n),不满足O(n)的要求。
  2. 哈希表法:将所有数字存入哈希集合,然后从1开始查找。时间和空间复杂度均为O(n),空间复杂度不满足O(1)的要求。

因此,我们必须另辟蹊径,利用题目给定的数组本身来作为“哈希表”,从而避免申请额外的空间。

核心思想:原地哈希(索引即键)

这个算法的核心思想是:将每个正整数x放到它应该在的位置,即索引x-1处。这样,数组的索引和值之间就建立了一一对应的关系。完成放置后,我们只需遍历数组,第一个nums[i] != i+1的位置,就是缺失的正数i+1

为了让这个“放置”过程顺利进行,我们需要进行几步预处理和巧妙的交换。

算法步骤详解

我们以nums = [3, 4, -1, 1]为例,来走一遍完整的流程。

第一步:预处理(处理非正数)
  • 目标:统一处理非正数,避免它们在后续交换中干扰索引。
  • 逻辑
    1. 首先,检查数组中是否存在1。如果不存在,直接返回1,因为1就是缺失的最小正数。
    2. 如果存在1,我们将数组中所有<= 0的数字都修改为1。这样,数组中的所有元素都变成了正数,方便后续操作。

为何要改为1因为我们只关心正数,将非正数改为1既不会丢失有用信息(1已经存在),又能防止它们参与交换时导致索引越界或逻辑混乱。

操作后:[3, 4, -1, 1]变为[3, 4, 1, 1]

第二步:交换元素到正确位置

这是算法的核心步骤。我们用一个指针i从左向右遍历数组。对于每个位置i,我们希望通过交换,让nums[i]这个值去到它“应该在”的索引nums[i]-1处。

交换过程遵循以下规则(使用for循环持续交换,直到当前位置的元素无法再归位):

  1. 待交换的值必须在有效范围内:即nums[i]的值必须介于1len(nums)之间。大于数组长度的值,无法在数组中找到对应的位置。
  2. 避免死循环:如果nums[i]已经在其正确的位置nums[nums[i]-1]上,或者目标位置的值已经与nums[i]相等(出现重复数字),则停止交换,i指针右移。

模拟交换过程:

  • i = 0nums[0] = 33应该在索引2处。
    交换nums[0]nums[2],数组变为[1, 4, 3, 1]
    nums[0]变为1,继续交换。1应该在索引0处,即当前位置,无需交换。指针i右移。

  • i = 1nums[1] = 44应该在索引3处。
    交换nums[1]nums[3],数组变为[1, 1, 3, 4]
    nums[1]变为1,无需交换。指针i右移。

  • i = 2nums[2] = 3:已经在正确位置。指针i右移。

  • i = 3nums[3] = 4:已经在正确位置。遍历结束。

最终数组状态:[1, 1, 3, 4]

第三步:扫描并返回结果

现在,数组已经“就位”。我们再次遍历数组,寻找第一个nums[i] != i+1的位置。

  • i = 0nums[0] == 1,正确。
  • i = 1nums[1] == 1不等于2

因此,缺失的第一个正数是2,直接返回。

如果所有位置都满足nums[i] == i+1,说明1len(nums)全部存在,那么答案就是len(nums)+1

代码实现(Golang)

funcfirstMissingPositive(nums[]int)int{n:=len(nums)hasOne:=false// 1. 预处理:检查1是否存在,并将非正数转为1fori:=0;i<n;i++{ifnums[i]==1{hasOne=true}elseifnums[i]<1{nums[i]=1}}if!hasOne{return1}// 2. 原地哈希:将每个数字x放到索引x-1处fori:=0;i<n;i++{// 持续交换,直到当前位置的值无法归位fornums[i]<=n&&nums[i]>0{// 如果目标位置已有正确值,或出现重复,则退出循环ifnums[i]==nums[nums[i]-1]{break}// 交换 nums[i] 和 nums[nums[i]-1]nums[i],nums[nums[i]-1]=nums[nums[i]-1],nums[i]}}// 3. 扫描查找第一个缺失的正数fori:=0;i<n;i++{ifnums[i]!=i+1{returni+1}}returnn+1}

复杂度分析

  • 时间复杂度:O(n)。虽然看起来有两层循环,但每个元素最多被交换一次,因此总的时间复杂度是线性的。
  • 空间复杂度:O(1)。我们只使用了常数个额外变量,所有操作都在原数组上进行。

总结

这道题的“原地哈希”解法,是算法中**“空间换时间”**思想的逆向应用——用时间换空间。它巧妙地将数组本身改造为哈希表,在不增加额外存储的前提下,利用索引与值的映射关系,高效地解决了问题。

掌握这种思想,对于解决一类“给定数组,寻找缺失/重复元素”的问题非常有帮助,例如 LeetCode 的第 448 题(找到所有数组中消失的数字)和 第 287 题(寻找重复数)都可以用类似思路解决。

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

相关文章:

  • 2026 年现阶段,沙坡头到聊城二手车物流公司哪家强,花几千块运二手车上牌,竟有人因此亏了半辆新车钱? - 实业推荐官
  • 龙岗网站建设怎么做好公司推广?资深运营揭秘本地企业数字化转型的真实套路
  • 如何让网站建设更高效?深度解析站内搜索在品牌官网中的核心价值与落地指南
  • 网站建设挣钱么:揭秘个人与工作室如何在红海中杀出一条血路并实现月入过万的真实路径
  • 2026年全国地上通风笼选购 靠谱厂家推荐指南 - 起跑123
  • 如何用Winhance中文版免费优化Windows系统:从卡顿到流畅的完整指南
  • 高通跃龙IQ-9100工业平台的开发经验分享(4): llm-重复输出与prompt工程解决方案
  • 2026年太原地区少儿美术培训辅导班选择参考指南 - 起跑123
  • 批量生图跑到一半挂了怎么办?给 nano-banana2 的生图API 任务加断点续跑
  • 2026 年至今,高坪正规的电液动推杆企业哪个好,用了它,车间里的重型物料推送效率竟提升了三倍? - 企业信息推荐-2
  • Linux 内核日志诊断:dmesg 命令完整详解(硬件故障排查实战)
  • 2026年宁波选购马尔轮廓仪 哪家好你可以多了解下这里 - 起跑123
  • Python 如何做文本对比?超全实战教程(精准比对+相似度+可视化差异)
  • 地铁采风111
  • 2026年集运系统大比拼,哪家能在众多竞品中脱颖而出?
  • 2026年选高速内镶贴条式滴灌带生产线正规厂商新润滴灌设备 - 热点品牌推荐
  • 2026年新版参考重庆市渐进老花镜怎么选?围绕容易忽略的风险和核对要点、这些问题要提前避开与区县服务要点全面解析 - 小校长
  • Visual C++运行库修复终极指南:一站式解决Windows应用程序启动问题的完整方案
  • 2026年买车去哪挑新能源汽车车行有哪些成都同展车多多新能源二手车 - 热点品牌推荐
  • 市场低代码管理平台智能管理
  • 2026年太原艺考生美术培训相关机构选择参考指南 - 起跑123
  • llama.cpp 本地部署完全指南:从安装到 OpenAI 兼容 API 服务
  • 高通跃龙IQ-9075平台的开发记录(1): 边缘农业AI助手的端到端部署
  • 2026年朝阳刑事律师事务所联系方式查询指南 北京英淇律师事务所(朝阳服务中心) - 热点品牌推荐
  • 嵌入式面试总结(六)——现代处理器架构
  • 2026年石家庄全自动软化水设备厂家如何选?春之原环境工程(石家庄营销部) - 热点品牌推荐
  • 2026年集运市场大揭秘:哪家集运系统能让你真正省心?
  • 郑州齿轮箱生产供应商哪家正规?选河南昊宇机械设备科技有限公司(郑州运营中心) - 热点品牌推荐
  • 全栈正式宣告死亡?
  • 历城区找中财静音管直营配送商哪家正规咨询济南淼森建材历城销售部 - 热点品牌推荐