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

Leetcode刷题记录28——缺失的第一个正数

题源:https://leetcode.cn/problems/first-missing-positive/description/?envType=study-plan-v2&envId=top-100-liked

题目描述:
在这里插入图片描述

思路一:

核心思想: 我们可以使用一个哈希集合(set)来记录nums中所有存在的整数,然后从 1 开始依次检查这些数字是否存在于集合中,一旦发现某个数字不存在,就返回它。
这种方法虽然没有达到最优的空间复杂度(O(1)),但它的实现简单、逻辑清晰,适用于大多数场景,特别是对时间和思维成本有限制的情况下。

具体实现步骤:
第一步: 使用 set() 构建哈希集合

hashmap = set(nums)

将原始数组转换成一个集合,这样做的好处是:

  • 去除重复元素。
  • 查询的时间复杂度降为 O(1)。

第二步: 从 1 开始查找第一个不在集合中的正整数

min_positive_num = 1
while min_positive_num in hashmap:min_positive_num += 1

我们从 1 开始不断递增,直到找到一个不在集合中的数字为止。
这个循环最多执行 n + 1 次(假设所有正整数都连续存在),因此时间复杂度是 O(n)。

⏱️ 时间与空间复杂度分析

时间复杂度:O(n),因为构建集合需要 O(n),查找过程最多遍历 n+1 个数字;
空间复杂度:O(n),因为使用了一个哈希集合保存所有不重复的元素。

✅ 优点:逻辑清晰、易于理解、编码简单
❌ 缺点:没有做到 O(1) 的空间复杂度,不满足题目中的常数级别要求,需要优化。

代码如下:

class Solution(object):def firstMissingPositive(self, nums):""":type nums: List[int]:rtype: int"""hashmap = set(nums)min_positive_num = 1while min_positive_num in hashmap:min_positive_num += 1return min_positive_num

执行时间如下:
在这里插入图片描述

思路二:

🧠 怎样可以做到 O(1) 空间?
题目中要求我们找出 最小的未出现的正整数。观察可知:

  • 如果数组长度是 n,那么答案一定在 [1, n+1] 范围内。
    • 比如 [1,2,3] 缺失的是 4;
    • 比如 [1,2,4] 缺失的是 3;
    • 所以只要我们能判断出 [1, n] 中哪些数字出现了,就能找到第一个没出现的。

那我们就可以尝试把每个数字放到它“应该在”的位置上:

  • 数字 1 放到索引 0
  • 数字 2 放到索引 1
  • 数字 x 放到索引 x - 1

这样处理后,再次遍历数组,如果某个位置上的数字不是它“应该有的”,就说明这个数字缺失了。

通过 原地哈希 的方式,我们可以将原本需要哈希表或集合辅助的方法优化到 常量级空间复杂度 O(1)。这种思想的核心在于:将原始数组作为隐式的哈希表来使用,把每个数字放到它应该出现的位置上(如数字 x 放到索引 x - 1 处),这样就能通过一次遍历找到缺失的最小正整数。

具体实现步骤:

第一步:将每个数放到其“正确”的位置

for i in range(nums_len):while 1 <= nums[i] <= nums_len and nums[nums[i] - 1] != nums[i]:correct_index = nums[i] - 1nums[correct_index], nums[i] = nums[i], nums[correct_index]

这段代码的作用是:

  • 如果当前数字 nums[i] 在合法范围内 [1, nums_len],并且不在它应该在的位置 nums[nums[i] - 1] 上,就把它交换到对应的位置上去。

举个例子:

  • 当前元素是 3,而 nums[2] 不等于 3,就交换。
  • 这样不断交换,直到当前位置上的元素已经在正确的位置上为止。

⚠️ 注意:这个循环必须使用 while,不能用 if,因为每次交换可能只移动了一个元素,还需要继续检查新的 nums[i] 是否也需要调整。

第二步:查找第一个不符合期望的位置

for i in range(nums_len):if nums[i] != i + 1:return i + 1

此时,如果某个位置 i 上的值不是 i + 1,说明这个正整数缺失,返回即可。

第三步:所有位置都符合预期,则返回 n + 1

return nums_len + 1

表示从 1 到 n 都存在,那么最小缺失的就是 n + 1。

⏱️ 时间与空间复杂度分析

时间复杂度:O(n) ,因为每个元素最多被交换一次。
空间复杂度:O(1) ,原地操作,没有使用额外数据结构。

代码如下:

class Solution(object):def firstMissingPositive(self, nums):""":type nums: List[int]:rtype: int"""nums_len = len(nums)for i in range(nums_len):while 1 <= nums[i] <= nums_len and nums[nums[i] - 1] != nums[i]:correct_index = nums[i] - 1nums[correct_index], nums[i] = nums[i], nums[correct_index]for i in range(nums_len):if nums[i] != i + 1:return i + 1return nums_len + 1

执行时间如下,空间复杂度得到了明显改善(25.66MB -> 19.87MB):
在这里插入图片描述

相关文章:

  • 优化高搜索量还是低竞争关键词?SEO策略解析
  • 神经网络的基本概念与深度解析——基于生物机制的仿生建模与工程实现
  • Redis 脚本:深入理解与实践指南
  • LabVIEW三轴电机控制
  • Python函数参数机制深度解析与最佳实践
  • 用docker ffmpeg测试视频vmaf分数,很快不用编译
  • Linux中安装mysql8,转载及注意事项
  • 微服务设计约束
  • 【浅学】Windows下ffmpeg+nginx+flv将本地视频推流在本地搭建的Web前端页面中播放,超详细步骤
  • WITH在MYSQL中的用法
  • Vscode/Code-Server 安装中文包——CI/CD
  • Ubuntu下安装Node.js
  • 使用Maxscript随机化对象
  • 【KWDB 创作者计划】Docker单机环境下KWDB集群快速搭建指南
  • C++的内存
  • 从实列中学习linux shell10 : 如何根据服务器的内存,cpu 以及 ssd硬盘 来确定mysql 的最大并发数
  • CGI(Common Gateway Interface)协议详解
  • rfsoc petalinux适配调试记录
  • JetBrains 开源python代码生成专用模型:Mellum-4b-sft-python
  • 【LeetCode Hot100】栈篇
  • 个人住房公积金贷款利率下调,100万元30年期贷款总利息将减少近5万元
  • 外交部发言人就当前印巴局势答记者问
  • 魔都眼|上海多家商场打开绿色通道,助力外贸出口商品转内销
  • 李云泽:大型保险集团资本补充已经提上日程
  • 关税风暴下,3G资本拟94亿美元私有化美国鞋履巨头斯凯奇,溢价30%
  • 马上评|从一个细节看今年五一档电影