LeetCode41- 缺失的第一个正数 | 算法练习系列

76 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情

前言

今天来一道数组相关的题目,题目难度为困难等级,看到这个困难搞的我都多想了,导致我自己想的太复杂,搞了好久,下面先来看一下题目描述吧。

题目描述

给你一个未排序的整数数组 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,n+1],然后判断当前项在不在哈希表中就可以了 代码如下:
/**
 * @param {number[]} nums
 * @return {number}
 */
var firstMissingPositive = function (nums) {
    var map = new Map()
    for (let i = 0; i < nums.length; i++) {
        if (!map.get(nums[i])) {
            map.set(nums[i], 1)
        }
    }
  
   
        for (let j = 1; j <= nums.length+1; j++) {
            if (!map.get(j)) {
                return j
            }
        }

};

运行结果如下:

image.png

上述方法可以成功提交通过,其实可以完全不用哈希表,直接遍历[1,n+1],然后用array.indexOf(j)来判断是不是等于-1就可以了,但是这样会超过时间限制。如下:

/**
 * @param {number[]} nums
 * @return {number}
 */
var firstMissingPositive = function (nums) {
    // var map = new Map()
    // for (let i = 0; i < nums.length; i++) {
    //     if (!map.get(nums[i])) {
    //         map.set(nums[i], 1)
    //     }
    // }
  
   
        for (let j = 1; j <= nums.length+1; j++) {
            if (nums.indexOf(j)===-1) {
                return j
            }
        }



};

image.png

优化

这一题中提到的达到空间的O(1)还是很有意思的,要实现这个可以借助原数组来实现一种类似哈希表的东西。具体步骤如下:

  • 首先把数组中小于0的项给改变了,可以改变成任意大约N的数
  • 然后遍历这个数组,拿当前项和数组的长度进行对比,如果小于长度的话就把num-1标记为负
  • 遍历标记后的数据,第一个大于0的项的下标加1就是结果 代码如下:
/**
 * @param {number[]} nums
 * @return {number}
 */
var firstMissingPositive = function (nums) {
    for (let i = 0; i < nums.length; ++i) {
        if (nums[i] <= 0) {
            nums[i] = nums.length + 1;
        }
    }
    for (let i = 0; i < nums.length; ++i) {
        let num = Math.abs(nums[i]);
        if (num <= nums.length) {
            nums[num - 1] = -Math.abs(nums[num - 1]);//这里有点难理解,打标记的其实是下标位置的数,也就是打标记的下标
        }
    }
    for (let i = 0; i < nums.length; ++i) {
        if (nums[i] > 0) {
            return i + 1;
        }
    }
    return nums.length + 1;

};

结果如下:

image.png