leetcode 41. 缺失的第一个正数

问题描述

给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
示例 1:
输入: [1,2,0]
输出: 3
示例 2:
输入: [3,4,-1,1]
输出: 2
示例 3:
输入: [7,8,9,11,12]
输出: 1
说明:
你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。

代码1

首先给一个空间复杂度为\(O(N)\)的算法,用map数组记录[1,n]之间的数字是否出现,大于n的数字与小于0的数字不用考虑,因为这肯定不是缺少的第一个正数,最后我们返回的是n+1,是考虑例子[1,2,0]这种情况。

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n = nums.size(),i;
        vector<int> map(n,0);
        for(i = 0; i < n; i++)
        {
            if(nums[i] <= n && nums[i] > 0)
                map[nums[i]-1] = 1;
        }
        for(i = 0; i < n; i++)
        {
            if(map[i] == 0)
                return i+1; 
        }
        return n+1;
    }
};

结果

执行用时 :12 ms, 在所有 C++ 提交中击败了29.88%的用户
内存消耗 :12.2 MB, 在所有 C++ 提交中击败了5.19%的用户

代码2

当然题目要求我们使用常数的空间复杂度,既然不能建立新的数组,那么我们只能覆盖原有数组,我们的思路是把1放在数组第一个位置nums[0],2放在第二个位置nums[1],即需要把nums[i]放在nums[nums[i] - 1]上,那么我们遍历整个数组,如果nums[i] != i + 1, 而nums[i]为整数且不大于n,另外nums[i]不等于nums[nums[i] - 1]的话,我们将两者位置调换,如果不满足上述条件直接跳过,最后我们再遍历一遍数组,如果对应位置上的数不正确则返回正确的数。注意for循环里面是while循环而不是if,是让正确的数在正确的位置上为止。

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n = nums.size(),i;
        for(i = 0; i < n; i++)
        {
            while(nums[i] <= n && nums[i] > 0 && nums[i] != nums[nums[i]-1])
                swap(nums[nums[i]-1],nums[i]);
        }
        for(i = 0; i < n; i++)
        {
            if(nums[i] != i+1)
                return i+1;
        }
        return n+1;
        
    }
};

结果

执行用时 :8 ms, 在所有 C++ 提交中击败了29.88%的用户
内存消耗 :12.3 MB, 在所有 C++ 提交中击败了5.19%的用户
posted @ 2020-03-03 08:46  曲径通霄  阅读(122)  评论(0编辑  收藏  举报