一起学习LeetCode热题100道(17/100)

17.缺失的第一个正数(学习)

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

示例 1:
输入:nums = [1,2,0]
输出:3
解释:范围 [1,2] 中的数字都在数组中。

示例 2:
输入:nums = [3,4,-1,1]
输出:2
解释:1 在数组中,但 2 没有。

示例 3:
输入:nums = [7,8,9,11,12]
输出:1
解释:最小的正数 1 没有出现。

提示:
1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1

解析:
一、清除无效数字:
遍历数组,将所有非正整数(即小于等于0的数)和超出数组长度的数(即大于 n 的数,其中 n 是数组长度)替换为一个不可能在 [1, n] 范围内出现的值,比如 n + 1。这样做是为了避免这些无效数字干扰后续的映射过程。

二、映射正整数到索引位置:
再次遍历数组,对于每个有效的正整数 num(即 1 <= num <= n),我们将其对应的索引 num - 1 上的元素取反(或设置为一个特定的标记值,但这里使用取反是因为它只需要一位操作,且容易在后续检查中恢复)。注意,如果索引 num - 1 上的元素已经是负数(或已经是我们的标记值),则不需要再次取反,因为这意味着该数字之前已经被处理过了(可能是数组中存在重复的数字)。

三、找到第一个未标记的索引:
遍历数组,找到第一个仍然是正数的元素。由于我们已经将有效正整数对应的索引位置上的元素取反(或标记),因此第一个正数对应的索引加1就是缺失的最小正整数。

四、处理所有索引都被标记的情况:
如果遍历完整个数组后都没有找到正数,说明 [1, n] 范围内的所有整数都在数组中出现了(以取反或标记的形式),那么缺失的最小正整数就是 n + 1。

var firstMissingPositive = function(nums) {
    const n = nums.length;  
  
    // Step 1: 清除无效数字(非正整数),并将超出范围的数替换为n+1(或其他无效值)  
    for (let i = 0; i < n; i++) {  
        if (nums[i] <= 0 || nums[i] > n) {  
            nums[i] = n + 1; // 替换为无效值  
        }  
    }  
  
    // Step 2: 映射正整数到索引位置(使用正负号或特定值标记)  
    // 注意:我们需要避免重复映射和错误映射  
    for (let i = 0; i < n; i++) {  
        let num = Math.abs(nums[i]);  
        if (num <= n) {  
            // 只处理尚未被标记过的、且在范围内的数字  
            if (nums[num - 1] > 0) {  
                nums[num - 1] *= -1; // 使用负数标记为已出现  
            }  
            // 如果nums[num-1]已经是负数,说明之前已经处理过这个数字了,无需再次处理  
        }  
    }  
  
    // Step 3: 找到第一个未标记的索引(即正数)  
    for (let i = 0; i < n; i++) {  
        if (nums[i] > 0) {  
            // 如果找到了正数,说明i+1是缺失的最小正整数  
            return i + 1;  
        }  
    }  
  
    // 如果所有索引都被标记了(即都是负数),则最小的正整数是n+1  
    return n + 1;  
};
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值