*LeetCode.1539 第 k 个缺失的正整数* [枚举和二分] | 刷题打卡

358 阅读1分钟

题目描述

给你一个 严格升序排列 的正整数数组 arr 和一个整数 k

请你找到这个数组里第 k 个缺失的正整数。

示例 1:

输入:arr = [2,3,4,7,11], k = 5
输出:9
解释:缺失的正整数包括 [1,5,6,8,9,10,12,13,...] 。第 5 个缺失的正整数为 9 。

示例 2:

输入:arr = [1,2,3,4], k = 2
输出:6
解释:缺失的正整数包括 [5,6,7,...] 。第 2 个缺失的正整数为 6 。

提示:

  • 1 <= arr.length <= 1000
  • 1 <= arr[i] <= 1000
  • 1 <= k <= 1000
  • 对于所有 1 <= i < j <= arr.lengthij 满足 arr[i] < arr[j]

思路讲解

这道题可以用枚举法,也可以用二分法。我们先来看用枚举法怎么做

枚举法

我们用一个current变量记录当前应该出现的数组。从 1 开始,每次循环都让该变量递增。用一个指针 ptr 指向数组中没有匹配的第一个元素,每轮循环中将该元素和current 进行比较,如果相等,则指针后移,否则指针留在原地不动,说明缺失正整数 current。我们用 missCount 变量记录缺失的正整数的个数,每次发现有正整数缺失的时候,该变量自增,并且记录这个缺失的正整数,直到我们找到第 k 个缺失的正整数。

var findKthPositive = function(arr, k) {
    let missCount = 0, lastMiss = -1, current = 1, ptr = 0; 
    for (missCount = 0; missCount < k; ++current) {
        if (current == arr[ptr]) {
            ptr = (ptr + 1 < arr.length) ? ptr + 1 : ptr;
        } else {
            ++missCount;
            lastMiss = current;
        }
    }
    return lastMiss;
};

二分法

二分法的原理就是如果数组是严格递增的,那么arr[i]应该等于i。那么arr[mid] -(1+mid)就是当前缺少的数字的数量,将这个数与k比较,就可以得到left和right。left等于right时,left+k就是第k个缺失的正整数。

/**
 * @param {number[]} arr
 * @param {number} k
 * @return {number}
 */
var findKthPositive = function (arr, k) {
    let left = 0, right = arr.length, mid
    while (left < right) {
        mid = (left + right) >> 1//右移运算符>>,运算结果正好能对应一个整数的二分之一值,这就正好能代替数学上的除2运算,但是比除2运算要快。
        if (arr[mid] - 1 - mid < k) {
            left = mid + 1
        } else {
            right = mid
        }
    }
    return left + k
};

总结

最简单的方法就是使用数组的方法indexOf()或者find()方法。遍历1-arr.length+k。如果indexOf(i) == -1 说明这个数不在数组中,num++,如果num == k就返回此时的i。

/**
 * @param {number[]} arr
 * @param {number} k
 * @return {number}
 */
var findKthPositive = function(arr, k) {
    let num = 0
    for (let i = 1; i <= arr.length + k; i++ ) {
        if (arr.indexOf(i) < 0) {
            num++
        }
        if (num == k) {
            return i
        }
    }
};

本题之所以可以用二分法来算。主要就是数组的下标和数组的值具有某种关系。值-下标就是此时有几个缺失的正整数。所以就可以用二分法来确定第k个正整数的范围。

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情