力扣每日一题41:缺失的第一个正数

题目描述:

给你一个未排序的整数数组 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

通过次数

325.7K

提交次数

749K

通过率

43.5%

思路和题解:

设数组长度为n,则确实的第一个正数只能在1,n+1的闭区间

思路一:暴力搜索。时间O(n^2),空间O(1),不符合要求

依次判断1,n在不在数组里,如果不在就返回那个不在的数,如果都在就返回n+1。代码。

复制代码
//暴力循环
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n=nums.size();
        for(int i=1;i<=n;i++)
        {
            bool flag=false;
            for(int j=0;j<n;j++)
            {
                if(nums[j]==i)
                {flag=true;break;}
            }
            if(!flag) return i;
        }
        return n+1;
    }
};

思路二:普通的哈希表。时间O(n),空间O(n),不符合要求。

用一个长度为n的数组来标记1,n有没有出现过。

复制代码
//普通哈希表
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n=nums.size();
        vector<bool> hash(n,false);
        for(int i=0;i<n;i++)
        {//出现了就标记为真
            if(nums[i]>0&&nums[i]<=n)
            hash[nums[i]-1]=true;
        }
        for(int i=0;i<n;i++)
        {
            if(hash[i]==false) return i+1;
        }
        return n+1;
    }
};

思路三:原地哈希表。时间O(n),空间O(1)

思路二是我们能想到的比较好的办法了,但是空间复杂度还是不能达到要求,那我们怎么来优化这个空间复杂度O(n)呢?要知道,只用O(n)的时间复杂度,也就是只用一层的循环,要找出缺失的第一个正数的话,不用其他空间来存储正数存在的状态时不可能的。既然必须要用空间来存储一些状态,又只能额外使用常数的空间,那我们只好拿给定的数组nums作为存储状态的空间。也就是说用原数组nums作为哈希表。

问题是怎么标记一个正数是否出现的状态。对于num<=0&&num>n的数,num在1,n之外无论怎么变化,都不会改变答案。那就干脆先把数组里所有<=0的数先变成n+1,之后再遍历数组,把每个1,n内的数num对应下标处都改为负数。最后再遍历一遍数组,对应元素不为负就说明这个数对应的位置是第一个缺失的正数。

复制代码
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {//原地哈希表
    //第一个缺失的数只能出现在[1,n+1]的闭区间里
        int n=nums.size();
        for(int i=0;i<n;i++)
        {//若出现负数或零或大于n的数,那第一个确实的数就在[1,n]
            if(nums[i]<=0) nums[i]=n+1;
        }
        for(int i=0;i<n;i++)
        {//将[num-1]标记为负,表示正数num没有缺失,num>n时不用管
            int num=abs(nums[i]);
            if(num<=n)
            {
                nums[num-1]=-abs(nums[num-1]);
            }
        }
        for(int i=0;i<n;i++)
        {
            if(nums[i]>0) return i+1;
        }
        return n+1;
    }
};
相关推荐
find1star5 小时前
LeetCode 141:环形链表
java·算法·leetcode·链表
迅翼SwiftWing5 小时前
编队系列(总)|固定翼编队如何实现稳定飞行?通信架构、协同算法与工程约束深度解析
算法·架构
LB21125 小时前
力扣160 21 86
算法·leetcode·职场和发展
小智老师PMP6 小时前
2026深度解析|PMP第八版与NPDP核心侧重点本质区别(管理类证书怎么选)
开发语言·分布式·算法·职场和发展·产品经理
HugoStudio_SWAN7 小时前
洛谷 B4450 / B3867 / B3923 智慧购物、储蓄与做题——从程序到生活
c++·学习·程序人生·算法·生活
a187927218317 小时前
【算法】动态规划第二篇:双序列 DP 三课——继承、计步与断链
算法·leetcode·动态规划·dp·回溯·暴力·算法讲解
江畔柳前堤8 小时前
前台·中台·后台:2026年AI原生时代的架构全景图
开发语言·人工智能·算法·机器学习·架构·scala·ai-native
文心快码BaiduComate8 小时前
2026 OPC x AI Coding 趋势案例交流会圆满落幕:一个人就一支研发团队
算法
ACM-moran8 小时前
条件显化(二分单峰函数+构造数列)
算法·推公式·整数三分
闻缺陷则喜何志丹9 小时前
【栈 运算系统】P3719 [AHOI2017初中组] rexp|普及+
c++·算法··洛谷·运算系统