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

LeetCode 题解 41. 缺失的第一个正数

41. 缺失的第一个正数

给你一个未排序的整数数组 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

题解

题目看起来很简单,寻找未出现过的最小正整数

很自然的想法就是用哈希表统计各个数字出现的次数,然后从1开始递增寻找是否出现过,第一个未出现的数字就是答案

但是注意到题目的要求是只使用常数级别额外空间的解决方案,也就是说不能开辟一个哈希表,需要在原数组上进行操作

接着对题目进行分析,我们发现:对于 n 个数的数组,最大的答案为 n+1,即数组内是 1,2,3…n 这些数各一个
否则只要有任何一个 1~n 之外或者重复的数,那么1~n之间必定有数字没出现,最小的即为我们的答案

  • 所以答案在 1~n+1 之间,而对于数组我们只关心 1~n 之间的数字,其余的数字对答案没有影响

接下来我们考虑如何在数组内原地操作

由于我们仅关心 1~n 的数字,而原数组恰好又是 n 大小,不妨将原数组作为哈希表,记录 1~n
用 nums[i] 记录 i+1
我们并不能直接用 nums[i] 记录 i+1 出现的次数,因为原数组内存储着需要的数据,不能直接修改原数组中的数据
那么我们不妨“一个萝卜一个坑",将 nums[i] 放到下标为 nums[i]-1 的位置上,并且考虑到不能修改原数组,我们将 nums[i] 与 nums[nums[i]-1] 进行交换,于是我们遍历数组,将数字放到对应的位置上,最后再遍历数组,第一个数字与位置不对的位置就是我们的答案

实现细节

  1. 遍历数组,此时位置为 i
  2. 如果 nums[i] 在 1~n 之外,我们不用处理它,因为它对答案没有影响
  3. 如果 nums[i] 在 1~n 之间,我们需要判断位置 nums[i]-1 上是否已经放置了对应的数 num[i]它是否在位置 nums[i]-1 上) ,没有的话就将其与对应位置的数进行交换,否则同样不做处理
  4. 然后我们接着看位置 i 上换来的新数据,重复以上过程
  5. 位置 i 处理结束后 i++
  • 注意,数组中会含有重复的数据
    因此步骤3我们不能去直接判断数字 nums[i] 是否在对应位置 nums[i]-1 上
    因为位置 nums[i]-1 上的数可能是另一个 nums[i],这样我们交换后再看换来的 nums[i],由于 nums[i] 不在对应位置,会接着把之前换过去的 nums[i] 换回来,这样就死循环了
    为了应对这种情况,我们直接去判断 nums[i] 对应的位置上是否是正确的数,是正确的数就不用处理了,多余的数和范围外的数一样对答案没有影响,这样面对重复的数字就不会一直交换了

代码如下↓

class Solution {
public:int firstMissingPositive(vector<int>& nums) {int n=nums.size();int res=n+1;for(int i=0;i<n;i++){if(nums[i]>=1 && nums[i]<=n && nums[i]!=nums[nums[i]-1]){swap(nums[nums[i]-1],nums[i]);i--;}}for(int i=0;i<n;i++){if(nums[i]!=i+1){res=i+1;break;}}return res;}
};
http://www.xdnf.cn/news/452989.html

相关文章:

  • 静电的起因与静电效应:技术分析与应用
  • svn status . 命令返回分析
  • 交易所功能设计的核心架构与创新实践
  • 论文查询的ai工具 —— SCAICH
  • 总共76dp 空出20dp然后放一个控件的写法
  • Shell和Bash介绍
  • PT2022E单触控三段LED调光IC
  • 云渲染实用指南:如何高效省心地使用炫云平台
  • JVM 精华
  • [特殊字符] GSG 插件 + 渲染 101:C4D 渲染效率革命!
  • 程序设计语言----软考中级软件设计师(自用学习笔记)
  • 防御保护-----第十三章:L2TP VPN
  • 强力巨彩谷亚推出专业智慧显示屏,满足多元场景需求
  • Java 垃圾回收机制深度解析与优化实践
  • IO复用详解——C/C++
  • 远程连接工具
  • Spring AOP的注解实现(自定义注解实现日志管理)
  • 17.电话号码的字母组合
  • P1220 关路灯
  • 放苹果(动态规划问题/一点♥的思考)
  • 【三维重建】三维场景生成:综述
  • 618开售仅1小时,李佳琦直播间加购同增超10%
  • Python Unicode字符串和普通字符串转换
  • 掌握Docker:从运行到挂载的全面指南
  • 位与运算
  • 一般枚举题目合集
  • Reverse-WP记录11
  • 如何利用PPG实现呼吸频率检测
  • CD38.【C++ Dev】string类的模拟实现(2)
  • 浏览器渲染原理