力扣热门100题之缺失的第一个正数【困难】

题目描述

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

本来想去重 但是查重复杂度太高

js![在这里插入图片描述](https://img-blog.csdnimg.cn/500eb3c0fbf341cc8f299322ed19838e.png) 复制代码
/**
 * @param {number[]} numArr
 * @return {number}
 */
var firstMissingPositive = function(nums) {
    let numArr=[]
    nums.forEach((v)=>{
        if(v>0){
            numArr.push(v);
        }
    })
    if(numArr.length==0){
        return 1;
    }
    if(numArr.length==1&&numArr[0]>1){
        return 1;
    }
    numArr.sort((a,b)=>parseInt(a)-parseInt(b))
    let min=1;
    for(let i=0;i<numArr.length;i++){
         if(min!=numArr[i]){
            return min;
        }
        if(min==numArr[i]&&numArr[i+1]!=min){
            min++;
        }
    }
    return min;
};

执行结果:

解法2 map+自增枚举

js 复制代码
/**
 * @param {number[]} numArr
 * @return {number}
 */
var firstMissingPositive = function(nums) {
    let map=new Map();
    nums.forEach(v=>{
        if(v>0){
			map.set(v,1);//过滤掉负数和0 节约has方法的时间
        }
    });
    let num=1;
    while(true){
        if(map.has(num)){
            num++;
        }else{
            return num;
        }
    }
};

执行结果:

解法3 数组替换

将原数组有的数替换到新的数组中 使得值i 与新数组i 对应 即 a[i]=i;

js 复制代码
/**
 * @param {number[]} numArr
 * @return {number}
 */
var firstMissingPositive = function(nums) {
    let numArr=[]
    for(let i=0;i<nums.length;i++){
        numArr[nums[i]]=nums[i];
    }
    if(numArr[1]!=1)return 1;
    for(let i=1;i<numArr.length;i++){
        if(numArr[i]!=i){
            return i;
        }
    }
    return numArr.length;
};

执行结果:

解法4 标记法

js 复制代码
/**
 * @param {number[]} nums
 * @return {number} 核心思想 长度为n的数组,其值为(1-n) 若其值不再这个范围内 那么1-n内必有一个缺失的正数找出这个数即可
 */
var firstMissingPositive = function(nums) {
    let n=nums.length;
    if(nums.indexOf(1)==-1)return 1;
    // 把负数和0变成1
    for(let i=0;i<n;i++){
        if(nums[i]<=0||nums[i]>n){
            nums[i]=1;
        }
    }
    // 到此全为1-n内的正数
    let index=0;
    for(let i=0;i<n;i++){
        index=Math.abs(nums[i])-1
        nums[index]=-Math.abs(nums[index]);
    }
    //查找第一个负数
    for(let i=0;i<n;i++){
        if(nums[i]>0){
            return i+1;
        }
    }
    return n+1;
};

执行结果:

解法5 置换法

3, 4, -1, 1\] 为例,置换后为=\>\[1, -1, 3, 4

0, 1, 2, 2\]===\>\[ 1, 2, 0, 1

js 复制代码
/**
 * @param {number[]} nums
 * @return {number}
 */
var firstMissingPositive = function(nums) {
    let n=nums.length;
    for(let i=0;i<n;i++){
        while(nums[i] > 0 && nums[i] <= n && nums[nums[i]-1] != nums[i]){
            //把对应元素交换到对应位置
            let temp=nums[nums[i]-1];
            nums[nums[i]-1]=nums[i];
            nums[i]=temp;
        }

    }
    for(let i=0;i<n;i++){
        if(nums[i]!=i+1){
            return i+1;
        }
    }
    return n+1;
};

执行结果:

相关推荐
Chengbei111 分钟前
Chrome浏览器渗透利器支持原生扫描!JS 端点 + 敏感目录 + 原型污染自动化检测|VulnRadar
javascript·chrome·安全·web安全·网络安全·自动化·系统安全
nglff5 分钟前
蓝桥杯抱佛脚第一天|简单模拟,set,map的使用
算法·职场和发展·蓝桥杯
愣头不青9 分钟前
560.和为k的子数组
java·数据结构
仟濹11 分钟前
【算法打卡day27(2026-03-19 周四)】蓝桥云课中Lv.1难度中的绝大部分题
算法·蓝桥杯
罗湖老棍子17 分钟前
滑动窗口与双调队列:幕布覆盖问题(定右缩左满分板子)改编自LeetCode 1438
算法·滑动窗口·单调队列
CoovallyAIHub21 分钟前
ICLR 2026 | MedAgent-Pro:用 Agent 工作流模拟临床医生的循证诊断过程
深度学习·算法·计算机视觉
实心儿儿22 分钟前
算法7:两个数组的交集
算法·leetcode·职场和发展
我可能是个假开发22 分钟前
算法-回溯
算法
WolfGang00732123 分钟前
代码随想录算法训练营 Day14 | 二叉树 part04
数据结构·算法
爱丽_23 分钟前
GC 怎么判定“该回收谁”:GC Roots、可达性分析、四种引用与回收算法
java·jvm·算法