力扣_数组14—缺失的第一个正数

题目

示例 1:
输入: n u m s = [ 1 , 2 , 0 ] nums = [1,2,0] nums=[1,2,0]
输出: 3 3 3

示例 2:
输入: n u m s = [ 3 , 4 , − 1 , 1 ] nums = [3,4,-1,1] nums=[3,4,1,1]
输出: 2 2 2

示例 3:
输入: n u m s = [ 7 , 8 , 9 , 11 , 12 ] nums = [7,8,9,11,12] nums=[7,8,9,11,12]
输出: 1 1 1

请你实现时间复杂度为 O ( n ) O(n) O(n) 并且只使用常数级别额外空间的解决方案。

思路

  • 对于长度为 n n n 的数组,其缺失的第一个正数必在 [ 1 , n + 1 ] [1,n+1] [1,n+1]
  • 最简单的想法是:
    • 新建一个长度为 n n n 的数组 f l a g flag flag,初始化为0
    • 遍历 n u m s nums nums ,若 n u m s [ i ] nums[i] nums[i] [ 1 , n ] [1,n] [1,n] 范围内,将 f l a g [ n u m s [ i ] − 1 ] flag[nums[i]-1] flag[nums[i]1] 置为1
    • 遍历 f l a g flag flag,若 f l a g [ i ] = = 0 flag[i] == 0 flag[i]==0,返回 i + 1 i+1 i+1;若全为1,返回 n + 1 n+1 n+1
    • 复杂度为 O ( n ) O(n) O(n) 但不是常数级额外空间
  • 原地修改 n u m s nums nums 来代替 f l a g flag flag:
    • n u m s nums nums 中小于等于 0 0 0 的数置成大于等于 n + 1 n+1 n+1 的任意数(因为不关心小于等于0的数)
    • 遍历 n u m s nums nums ,若 a b s ( n u m s [ i ] ) abs(nums[i]) abs(nums[i]) [ 1 , n ] [1,n] [1,n] 范围内,则令 n u m s [ a b s ( n u m s [ i ] ) − 1 ] = − n u m s [ a b s ( n u m s [ i ] ) − 1 ] nums[abs(nums[i])-1] = -nums[abs(nums[i])-1] nums[abs(nums[i])1]=nums[abs(nums[i])1] (即把 n u m s [ a b s ( n u m s [ i ] ) − 1 ] nums[abs(nums[i])-1] nums[abs(nums[i])1] 加个负号,代替 f l a g flag flag 中的置1)
    • 遍历 n u m s nums nums,若 n u m s [ i ] > 0 nums[i] > 0 nums[i]>0,返回 i + 1 i+1 i+1;若全为1,返回 n + 1 n+1 n+1

代码

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

        // int n = nums.size();
        // for(int i = 0; i < n; i++){
        //     if(nums[i] <= 0)
        //         nums[i] = n+1;
        // }
        // for(int i = 0; i < n; i++){
        //     if(abs(nums[i])<n+1){
        //         nums[abs(nums[i])-1] = -abs(nums[abs(nums[i])-1]);
        //     }
        // }
        // for(int i = 0; i < n; i++){
        //     if(nums[i] > 0){
        //         return i+1;
        //     }
        // }
        // return n+1;

        // int n = nums.size();
        // for(int i = 0; i < n; i++){
        //     while(nums[i] > 0 && nums[i] < n+1 && nums[i] != nums[nums[i]-1]){
        //         swap(nums[i], nums[nums[i]-1]);
        //     }
        // }
        // for(int i = 0; i < n; i++){
        //     if(nums[i] != i+1){
        //         return i+1;
        //     }
        // }
        // return n+1;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值