【LeetCode每日一题】——1539.第 k 个缺失的正整数

一【题目类别】

  • 二分查找

二【题目难度】

  • 简单

三【题目编号】

  • 1539.第 k 个缺失的正整数

四【题目描述】

  • 给你一个 严格升序排列 的正整数数组 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 。

六【解题思路】

  • 利用二分查找的思想,不过找的不是目标值,而是缺失数字数量大于k的最小位置
  • 那么如何计算每个位置的缺失数字数量呢?可以用公式: a r r [ m i d ] − m i d − 1 arr[mid] - mid - 1 arr[mid]mid1计算,其中 m i d mid mid就是二分查找的中间值
  • 如果缺失数字数量大于或等于 k k k,说明需要向左查找,反之需要向右查找
  • 当找到缺失数字数量大于 k k k的最小位置后(用 l e f t left left表示),就可以计算第 k k k个缺失的数字了
  • a r r [ l e f t − 1 ] − ( l e f t − 1 ) − 1 arr[left - 1] - (left - 1) - 1 arr[left1](left1)1表示找到的位置缺失的数字数量, k − ( a r r [ l e f t − 1 ] − ( l e f t − 1 ) − 1 ) k - (arr[left - 1] - (left - 1) - 1) k(arr[left1](left1)1)就表示从 a r r [ l e f t − 1 ] arr[left - 1] arr[left1]开始还缺几个数字,最后再加上 a r r [ l e f t − 1 ] arr[left - 1] arr[left1]就是第 k k k个缺失的数字,这里 l e f t left left减一就是缺失数字数量和大于 k k k的最小位置,所以最后的计算公式就是 k − ( a r r [ l e f t − 1 ] − ( l e f t − 1 ) − 1 ) + a r r [ l e f t − 1 ] k - (arr[left - 1] - (left - 1) - 1) + arr[left - 1] k(arr[left1](left1)1)+arr[left1]
  • 另外还需要注意边界条件,如果数组的第一个数字都大于 k k k,说明第 k k k个缺失的数字就是 k k k,直接返回 k k k就行
  • 最后返回结果即可

七【题目提示】

  • 1 < = a r r . l e n g t h < = 1000 1 <= arr.length <= 1000 1<=arr.length<=1000
  • 1 < = a r r [ i ] < = 1000 1 <= arr[i] <= 1000 1<=arr[i]<=1000
  • 1 < = k < = 1000 1 <= k <= 1000 1<=k<=1000
  • 对于所有 1 < = i < j < = a r r . l e n g t h 的 i 和 j 满足 a r r [ i ] < a r r [ j ] 对于所有 1 <= i < j <= arr.length 的 i 和 j 满足 arr[i] < arr[j] 对于所有1<=i<j<=arr.lengthij满足arr[i]<arr[j]

八【题目进阶】

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

九【时间频度】

  • 时间复杂度: O ( l o g n ) O(logn) O(logn),其中 n n n为数组的长度
  • 空间复杂度: O ( 1 ) O(1) O(1)

十【代码实现】

  1. Java语言版
class Solution {
    public int findKthPositive(int[] arr, int k) {
        if(arr[0] > k){
            return k;
        }
        int left = 0;
        int right = arr.length;
        while(left < right){
            int mid = (left + right) / 2;
            int dif = arr[mid] - mid - 1;
            if(dif >= k){
                right = mid;
            }else{
                left = mid + 1;
            }
        }
        return k - (arr[left - 1] - (left - 1) - 1) + arr[left - 1];
    }
}
  1. C语言版
int findKthPositive(int* arr, int arrSize, int k)
{
    if(arr[0] > k)
    {
        return k;
    }
    int left = 0;
    int right = arrSize;
    while(left < right)
    {
        int mid = (left + right) / 2;
        int dif = arr[mid] - mid - 1;
        if(dif >= k)
        {
            right = mid;   
        }
        else
        {
            left = mid + 1;
        }
    }
    return k - (arr[left - 1] - (left - 1) - 1) + arr[left - 1];
}
  1. Python版
class Solution:
    def findKthPositive(self, arr: List[int], k: int) -> int:
        if arr[0] > k:
            return k
        left = 0
        right = len(arr)
        while left < right:
            mid = (left + right) // 2
            dif = arr[mid] - mid - 1
            if dif >= k:
                right = mid
            else:
                left = mid + 1
        return k - (arr[left - 1] - (left - 1) - 1) + arr[left - 1]

十一【提交结果】

  1. Java语言版
    在这里插入图片描述

  2. C语言版
    在这里插入图片描述

  3. Python语言版
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IronmanJay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值