zoukankan      html  css  js  c++  java
  • [LeetCode] 1539. Kth Missing Positive Number

    Given an array arr of positive integers sorted in a strictly increasing order, and an integer k.

    Find the kth positive integer that is missing from this array.

    Example 1:

    Input: arr = [2,3,4,7,11], k = 5
    Output: 9
    Explanation: The missing positive integers are [1,5,6,8,9,10,12,13,...]. 
    The 5th missing positive integer is 9.

    Example 2:

    Input: arr = [1,2,3,4], k = 2
    Output: 6
    Explanation: The missing positive integers are [5,6,7,...]. 
    The 2nd missing positive integer is 6.

    Constraints:

    • 1 <= arr.length <= 1000
    • 1 <= arr[i] <= 1000
    • 1 <= k <= 1000
    • arr[i] < arr[j] for 1 <= i < j <= arr.length

    第K个缺失的正整数。

    题意是给一个升序的数组和一个数字K,请返回第K个缺失的正整数。这道题和1060题是一模一样,但是这道题是easy的原因在于数据范围很小,nums[i] 只到1000。

    这道题有好几种解法,我这里都列出来。分别是暴力解,线性解和二分法。

    首先是暴力解,用一个指针扫描input数组,去看每一个位置上的数字是否是要找的数字target。一开始target = 1,意思是从1开始找,如果能在input数组中找到每个正整数,则接着往后遍历;但凡有一个正整数找不到,就把这个缺失的正整数加到一个list中,直到这个list的size达到K。但是也有可能list没有到K,input数组就遍历完了,此时可以把缺失的整数用一个while循环模拟完。

    时间O(n)

    空间O(n)

    Java实现

     1 class Solution {
     2     public int findKthPositive(int[] arr, int k) {
     3         int target = 1;
     4         int i = 0;
     5         List<Integer> missingOnes = new ArrayList<>();
     6         while (i < arr.length) {
     7             // if the target number is found
     8             if (arr[i] == target) {
     9                 i++;
    10                 target++;
    11             }
    12             // if it's not found
    13             else {
    14                 missingOnes.add(target);
    15                 target++;
    16             }
    17         }
    18         int size = missingOnes.size();
    19         int count = size;
    20         int lastNumber = (missingOnes.size() == 0) ? arr[arr.length - 1]
    21                 : Math.max(arr[arr.length - 1], missingOnes.get(missingOnes.size() - 1));
    22         if (count >= k) {
    23             return missingOnes.get(k - 1);
    24         } else {
    25             while (count < k) {
    26                 lastNumber++;
    27                 count++;
    28             }
    29             return lastNumber;
    30         }
    31     }
    32 }

    一个比较优化的线性解法是,因为题目给的是一个升序的正整数数组,而且数组理论上是从1开始。所以理想情况下,数字nums[i]和它对应的下标i的关系应该是nums[i] = i + 1。所以在扫描input数组的时候,如果发觉数字和他对应的下标的差大于1了,则说明中间开始缺失数字了。当这个差距大于等于K的时候,则找到了第K个缺失的数字。

    时间O(n)

    空间O(1)

    Java实现

     1 class Solution {
     2     public int findKthPositive(int[] arr, int k) {
     3         int len = arr.length;
     4         for (int i = 0; i < len; i++) {
     5             if (arr[i] - i - 1 >= k) {
     6                 return k + i;
     7             }
     8         }
     9         return k + len;
    10     }
    11 }

    二分法。因为input数组是有序的,所以如果面试官不满意O(n)级别的思路的话,可以试图往二分法上靠。mid找到中点,还是跟第二种做法类似,比较当前这个index上的数字和index的差值。如果差值小于K,则往数组的右半边找;反之则往数组的左半边找。

    时间O(logn)

    空间O(1)

    Java实现一,right 指针一开始在数组范围外

     1 class Solution {
     2     public int findKthPositive(int[] arr, int k) {
     3         int left = 0;
     4         int right = arr.length;
     5         int mid = 0;
     6         while (left < right) {
     7             mid = left + (right - left) / 2;
     8             if (arr[mid] - mid >= k + 1) {
     9                 right = mid;
    10             } else {
    11                 left = mid + 1;
    12             }
    13         }
    14         return left + k;
    15     }
    16 }

    Java实现二,right 指针一开始在数组范围内。因为 right = nums.length - 1,mid 指针能碰到的范围是在 [left, right] 之间,所以当 mid 不满足判断条件的时候,left = mid + 1,right = mid - 1。

     1 class Solution {
     2     public int findKthPositive(int[] arr, int k) {
     3         int left = 0;
     4         int right = arr.length - 1;
     5         while (left <= right) {
     6             int mid = left + (right - left) / 2;
     7             int missing = arr[mid] - mid - 1;
     8             if (missing < k) {
     9                 left = mid + 1;
    10             } else {
    11                 right = mid - 1;
    12             }
    13         }
    14         return left + k;
    15     }
    16 }

    JavaScript实现一

     1 /**
     2  * @param {number[]} arr
     3  * @param {number} k
     4  * @return {number}
     5  */
     6 var findKthPositive = function (arr, k) {
     7     let start = 0;
     8     let end = arr.length - 1;
     9     while (start <= end) {
    10         let mid = start + Math.floor((end - start) / 2);
    11         let missing = arr[mid] - mid - 1;
    12         if (missing < k) {
    13             start = mid + 1;
    14         } else {
    15             end = mid - 1;
    16         }
    17     }
    18     return start + k;
    19 };

    JavaScript实现二

     1 /**
     2  * @param {number[]} arr
     3  * @param {number} k
     4  * @return {number}
     5  */
     6 var findKthPositive = function (arr, k) {
     7     let start = 0;
     8     let end = arr.length;
     9     while (start < end) {
    10         let mid = start + Math.floor((end - start) / 2);
    11         let missing = arr[mid] - mid - 1;
    12         if (missing < k) {
    13             start = mid + 1;
    14         } else {
    15             end = mid;
    16         }
    17     }
    18     return start + k;
    19 };

    相关题目

    410. Split Array Largest Sum

    774. Minimize Max Distance to Gas Station

    875. Koko Eating Bananas

    1011. Capacity To Ship Packages In N Days

    1060. Missing Element in Sorted Array

    1231. Divide Chocolate

    1283. Find the Smallest Divisor Given a Threshold

    1482. Minimum Number of Days to Make m Bouquets

    1539. Kth Missing Positive Number

    LeetCode 题目总结

  • 相关阅读:
    做前端的一些小工具
    分析几种编程语言对JSON的支持程度
    注册中心eureka
    搭建分布式配置中心
    接口幂等性
    分布式限流
    服务容错解决方案
    微服务架构认知
    gateWay
    JWT鉴权
  • 原文地址:https://www.cnblogs.com/cnoodle/p/13632810.html
Copyright © 2011-2022 走看看