leetcode之路(缺失的第一个正数)
题目:
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
示例 1:
输入: [1,2,0]
输出: 3
示例 2:
输入: [3,4,-1,1]
输出: 2
示例 3:
输入: [7,8,9,11,12]
输出: 1
说明:
你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。
“实现一个功能如果需要10分钟,思考的时间是7分钟”
思考过程:
拿到题目最容易想到的方法是对数组先排序,然后从一往后找,就可以很轻松的找到缺失的正数。
**方法一:**使用sort()对数组进行排序,然后从1还是逐个找下一个正数,如果找到的结果大于应该出现的正数,说明该数即是所求。方法关键代码:
int firstMissingPositive(vector<int>& nums) {
int ret=1;
if(nums.size()==0)
return ret;
sort(nums.begin(),nums.end());
vector<int>::iterator iter=nums.begin();
for(;iter!=nums.end();iter++){
if(ret==*iter)
ret++;
else if(*iter>ret)
break;
}
return ret;
}
but题目要求中“你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。”sort()函数的时间复杂度为nlog2(n),显然我们的代码虽然可以求出题目的答案,但并不符合题目要求。于是就有了相对高级的方法二。
方法二: 方法二的思想与方法一无异,但是改进了一下排序的方法,我们使用交换位置的方法对原来的数组原地排序(当给我们的nums[0]是3时,我们可以让nums[0]与num[2]交换这样3就回到了正确的位置,直到nums[0]=1时再到nums[1]的值进行操作),根据题意我们只需对正数进行排序,但是有这么几种情况是我们无法找到正确的位置的:
1、nums[i]>nums.size(),或者nums[i]<1,这时的i-1下标越界,直接i++
2、nums[i]==nums[nums[i]-1],这个数对应位置上的数已经是正确的了,说明有重复数字,直接i++;
为了方便理解,附上一个例子:当nums={3,-1,4,6,1}时,该算法的运行过程为:
方法二的代码如下:
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
for(int i=0;i<nums.size();){
if(nums[i]<=0||nums[i]>nums.size()||nums[i]==i+1||nums[i]==nums[nums[i]-1])
i++;
else{
int tem;
tem=nums[nums[i]-1];
nums[nums[i]-1]=nums[i];
nums[i]=tem;}
}
for(int i=0;i<nums.size();i++){
if(nums[i]!=i+1)
return i+1;
}
return nums.size()+1;}
};
提交结果:
执行用时 :4 ms
, 在所有 C++ 提交中击败了86.60%的用户
内存消耗 :8.6 MB
, 在所有 C++ 提交中击败了81.74%的用户