LeetCode 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
思路
约束:
- 未排序 要求O(n) 不能使用排序算法 且对顺序有一定要求 考虑哈希表(集合)
- 常数级别的空间 不能使用哈希表(集合)
分析:
考虑答案范围,最小值可能是1,如所有数都大于1;当nums[i]=i+1时,答案取最大值,最大值是nums.size+1。故答案范围在[1,nums.size+1]。所以只需要从小到大遍历该范围,第一个未出现的数字就是答案。
考虑如果范围内某一数值x出现,则记录该值出现,自然想到集合或者哈希
难点:需要哈希表(集合),但不能使用哈希表(集合)
解决:
如何记录?利用nums数组,[1,nums.size+1] 需要n个位置记录,所以让nums[i]记录i-1是否出现
如果x在范围里,则用nums[x-1]保存该数字,原来的数据怎么办?将二者位置交换即可,交换之后,新数据有两种情况,在范围内,则需要继续交换,出现循环,考虑该操作有可能不停止吗,考虑一直在范围内的情况,也就是换了之后,目标位置符合条件nums[x-1]=x,同时本来的位置数值换过去也符合,也就是nums[i]=x, 出现了重复的数字,需要考虑该情况;不在范围内则停止处理。
eg: [3,4,1,-1]
i=0
第一次交换 [1,4,3,-1]
交换后1在范围内,继续交换[1,4,3,-1] (其实1已经在位置上了,可以省略) 交换后1在范围内,nums[0]=1,不需要继续交换
i=1
第一次交换[1,-1,3,4]
i=2
i=3
结果[1,-1,3,4]
遍历结果 第一个不符合 nums[i]!=i+1的 i+1就是答案
实现:
int firstMissingPositive(vector<int>& nums) {
for(int i=0;i<nums.size();i++) {
//进行哈希
while(nums[i]>0&&nums[i]<=nums.size()&&nums[i]!=i+1) {
int t = nums[i];
//需要考虑的死循环情况
if(nums[i]==nums[t-1])
break;
nums[i]=nums[t-1];
nums[t-1] = t;
}
}
for(int i=0;i<nums.size();i++) {
//找到第一个不符合条件的就是答案
if(nums[i]!=i+1) {
return i+1;
}
}
return nums.size()+1;
}
分类:
算法 / 数组
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· RFID实践——.NET IoT程序读取高频RFID卡/标签