持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情
第 28 天
缺失的第一个正数
题目
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。
示例 1:
输入:nums = [1,2,0]
输出:3
示例 2:
输入:nums = [3,4,-1,1]
输出:2
示例 3:
输入:nums = [7,8,9,11,12]
输出:1
提示:
1 <= nums.length <= 5 * 105
-231 <= nums[i] <= 231 - 1
题解
两种解法:
是最先容易想到的一种,即先把数组过滤成正整数,再进行升序排列,然后遍历后一个值减前一个值进行筛选。 这种解法问题在于排序多消耗了遍历次数。 这个在第一种解法基础上优化了一下,利用选择排序的原理(即每次遍历都会把最小值放到最左边),因此可以边遍历边对比值,从而减少遍历次数。
<!-- 解法二代码 -->
var firstMissingPositive = function(nums) {
// 利用选择排序的原理,减少数组遍历次数
nums = nums.filter(item=>{ return item > 0;})
let min;
for(let i = 0;i<nums.length; i++){
min = nums[i];
for(let j = i+1; j<nums.length; j++){
if(min > nums[j]){
let temp = min;
min = nums[j];
nums[j] = temp;
}
}
// 当把后面的值都遍历完后,当前值和标记出来的值交换位置
nums[i] = min;
if(i>0){
if(nums[i] - nums[i-1]>1){
return nums[i-1] + 1;
}
}else{ // 只遍历出第一个最小值时
if(min !== 1){
return 1;
}
}
}
// 如果数组是连续的正整数,注意:此处不能用数组长度直接+1,因为会有相同元素的数组情况,如[1,1]
return nums.length ? nums.pop() +1 : 1;
};
解法二:
var firstMissingPositive = function(nums) {
for (const num of nums)
if (typeof nums[+num - 1] !== 'undefined')
nums[+num - 1] = '' + nums[+num - 1]
for (let i = 0; i < nums.length; i++)
if (typeof nums[i] === 'number')
return i + 1
return nums.length + 1
};