leetcode之路(缺失的第一个正数)

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%的用户

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章