当前位置: 首页 > 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):
在这里插入图片描述

http://www.xdnf.cn/news/268453.html

相关文章:

  • 山东大学离散数学第十章习题解析
  • 测试基础笔记第十八天
  • PyTorch_创建01张量
  • 【深度学习基础】:VGG实战篇(图像风格迁移)
  • [Windows] Kazumi番剧采集v1.6.9:支持自定义规则+在线观看+弹幕,跨平台下载
  • ecs网站备份,ecs网站备份的方法
  • 基于YOLOv8的人流量识别分析系统
  • 普通 html 项目引入 tailwindcss
  • 【算法专题九】链表
  • Socket 编程 UDP
  • C++继承基础总结
  • GESP2024年6月认证C++八级( 第三部分编程题(2)空间跳跃)
  • VFS Global 携手 SAP 推动数字化转型
  • Three.js支持模型格式区别、建议
  • <property name=“userDao“ ref=“userDaoBean“/> 这两个的作用和语法
  • Java虚拟线程基础介绍
  • 23.合并k个升序序链表- 力扣(LeetCode)
  • Spring Cloud与Service Mesh集成:Istio服务网格实践
  • 【学习笔记】 强化学习:实用方法论
  • deepseek提供的Red Hat OpenShift Container Platform 4.X巡检手册
  • 深入理解Redis SDS:高性能字符串的终极设计指南
  • 基于Springboot高校网上缴费综合务系统【附源码】
  • CSS元素动画篇:基于当前位置的变换动画(合集篇)
  • 《算法导论(第4版)》阅读笔记:p2-p3
  • Java大师成长计划之第11天:Java Memory Model与Volatile关键字
  • 【Mytais系列】Myatis的设计模式
  • API接口:轻松获取企业联系方式
  • 理解Android Studio IDE工具
  • 虚幻基础:角色朝向
  • MIT6.S081-lab8前置