第 k 个缺失的正整数

190 阅读2分钟

这是我参与「掘金日新计划 · 2 月更文挑战」的第 27 天,点击查看活动详情

问题描述

给你一个 严格升序排列 的正整数数组 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.length 的 i 和 j 满足 arr[i] < arr[j] 

进阶:

你可以设计一个时间复杂度小于 O(n) 的算法解决此问题吗?

思路分析

首先我们先要理解一下题目意思,题目会给我们一个数组和一个整数,我们需要找到arr中缺失的第k个正整数,如arr = [2,3,4,7,11], k = 5缺失的正整数包括 [1,5,6,8,9,10,12,13,...] 。第 5 个缺失的正整数为 9 。

  • 遍历求值

最简单的方法是直接从1开始往后遍历,判断元素是否在arr中,不在的话则说明为缺失的元素,此时缺失元素计数加一,当计数为k时则说明找到了第k个缺失的正整数,代码如下:

/**
 * @param {number[]} arr
 * @param {number} k
 * @return {number}
 */
var findKthPositive = function (arr, k) {
    let i = 0,
      ind = 0;
    while (k) {
      i++;
      if (arr[ind] == i) ind++;
      else k--;
    }
    return i;
};

上述的方法的时间复杂度为O(n),那么有没有时间复杂度小于 O(n) 的算法可以解决此问题呢?答案是有的,我们可以直接计算arr中相邻两个元素之间的差值得出两元素间缺失的元素数量,当缺失元素数量达到k个时,我们即可快速计算出第k个缺失的正整数,具体代码如下:

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

说在后面

本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。