题目链接
41. 缺失的第一个正数 - 力扣(LeetCode) (leetcode-cn.com)
题目描述
给你一个未排序的整数数组 nums
,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n)
并且只使用常数级别额外空间的解决方案。
解题思路
不考虑常数级额外空间,可以使用hash表统计出现过的整数,再遍历寻找一个没有出现过的正整数;
考虑常数级的额外空间,不能使用hash表,选择通过置换的方式,尽量使每一个索引i对应的数字为i+1;
置换完毕后,遍历重新排列后的数组,如果第i个数字不是i+1,说明i+1未出现,返回i+1;
如果数组中所有的i都对应i+1,则数组长度n个正整数都出现了,返回下一个正整数n+1;
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int n = nums.size();
for(int i=0;i<n;i++){
while(nums[i] > 0 && nums[i] <= n && nums[nums[i]-1] != nums[i]){
swap(nums[i],nums[nums[i] - 1]);
}
}
for(int i=0;i<n;i++){
if(nums[i] != i+1){
return i+1;
}
}
return n+1;
}
};
标准答案
缺失的第一个正数 - 缺失的第一个正数 - 力扣(LeetCode) (leetcode-cn.com)
方法一:原地hash。
本题需要记录数字是否出现,即如果使用hash表,hash表的value只有0和1,可以采用改变数字正负号的形式实现原地hash,不适用额外的空间;
第一步,将所有非正整数规范化为不影响计数的整数n+1;
第二步,遍历数组,假如nums[i]的值再1-n之间,将索引为nums[i]-1的值改为负数,表示nums[i]出现过;
第三步,遍历数组,如果第i数位整数,则表示i+1未出现过,返回i+1;若全为负数,返回n+1;
方法二:置换,同解题思路。