困难
给你一个未排序的整数数组 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
题解: 数组中的数只有三种可能 全为正数
全为负数
有正有负数
对于第一种
,排序后判断数组头是否为1,不成立返回1,成立则循环判断数的连续
,返回使连续中断的那个数,若没有中断则代表数组尾的值+1为最小正整数(nums[n-1]+1)
对于第二种
,排序后返回1
即可.判断条件为nums[n-1]>0
对于第三种
,排序后对其进行排负
即循环判断找到一个正数,将这个正数的下标作为新数组头
进入第一种
简化上面的三种可能:
第一步判断判断数组头是否为1,判断数组是否全为负(排序后)判断条件为nums[nums.size()-1]<1||nums[0]>1
当有其中一项成立直接返回1
第二步如果数组中有负数(nums[n-1]>0
成立)则排负
,排负
后判断新数组头
是否大于1,成立直接返回1,否则循环判断数的连续
.如果数组中没有负数(nums[n-1]>0
不成立)则循环判断数的连续
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
sort(nums.begin(),nums.end());//升序排序,方便查找
int n=nums.size();
if(nums[n-1]<1||nums[0]>1)//数组全为负数时直接返回1 数组头为大于1同样返回1
return 1;
int j=0;//记录新数组头
if(nums[0]<0)//成立代表数组含有负数
for(int i=0;i<n;i++)//排负
if(nums[i]>0){
j=i;//下表定位到正数
if(nums[j]>1)//排负后数组头大于1直接返回1
return 1;
break;
}
for(int i=j;i<n-1;i++)//当数组没有负数且数组头不为1
if(nums[i]+1!=nums[i+1]&&nums[i]!=nums[i+1])//第一个条件判断数组是否连续 第二个条件判断两个数的重复 重复不会中断连续
return nums[i]+1;//返回使连续中断的那个数
return nums[n-1]+1;
}
};