【二分查找】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 。

提示

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

方法一:枚举法

解题思路

初始化基准值 pivot 为1,用 i = 0 指向数组中第一个没有匹配的元素,
若 arr[i] == pivot,说明 pivot 在数组中是存在的,指针 i 后移;若不相等,则说明当前 pivot 是缺失值,count 自增 1。如此循环下去,直到找到第 k 个缺失的正整数。

代码

class Solution {
public:
    int findKthPositive(vector<int>& arr, int k) {
        int count = 0, index = 0, pivot = 1;
        while(count < k)
        {
            if(arr[index] == pivot)
            {
                index = index + 1 < arr.size() ? index + 1: index;    
            }
            else
            {
                count++;
            }
            pivot++;
        }
        return pivot - 1;
    }
};

复杂度分析

  • 时间复杂度:O(n + k)。最坏的情况是,当数组中的元素都遍历完了,都没有缺失正整数。
  • 空间复杂度:O(1)。

方法二:二分查找

解题思路

假定 p i p_i pi 表示每一个下标处缺失的正整数的数量为 a[i] - i - 1。

第 i 个元素 a i a_i ai的值到第 i 个元素为止缺失的元素数量 p i p_i pi
a 0 a_0 a021
a 1 a_1 a131
a 2 a_2 a241
a 3 a_3 a373
a 4 a_4 a4116

不难发现, p i p_i pi 是随 i 非严格递增的,所以可以二分查找解决这道题目。
只要找到一个 i 使用 p i − 1 < k < = p i p_{i - 1} < k <= p_i pi1<k<=pi,就可以确定缺失的第 k 个正整数为 k − p i − 1 k - p_{i - 1} kpi1 + a[i - 1],所以要找到第一个大于等于 k 的 p i p_i pi
特殊情况:如果 arr[0] > k,说明第 k 个缺失的正整数就是 k,直接返回 k。

代码

class Solution {
public:
    int findKthPositive(vector<int>& arr, int k) {
        if(arr[0] > k)  return k;  
        int l = 0, r = arr.size(), mid;
        // 找到缺失数量大于 k 的最小位置
        while(l < r)
        {
            mid = (l + r) >> 1;
            if(arr[mid] - mid - 1 >= k) r = mid;
            else    l = mid + 1;
        }
        return k - (arr[l - 1] - (l - 1) - 1) + arr[l - 1];
    }
};

复杂度分析

  • 时间复杂度:O( l o g n logn logn)。
  • 空间复杂度:O(1)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值