一起刷力扣之【1539. 第 k 个缺失的正整数】

158 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

题目描述

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

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

示例

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

暴力法

通过枚举,逐个元素进行比较,累积得出最终结果。

class Solution {
    public int findKthPositive(int[] arr, int k) {
        // 定义一个结果变量,一个指针
        int res = 0, idx = 0;
        
        // i用来做为比较的数值,终止条件为k == 0
        for(int i = 1; k > 0; ++i){
            if(arr[idx] == i){
                // 当前元素不为缺失的数值,则指针后移,这里记得要做好边界处理
                idx = Math.min(idx + 1, arr.length - 1);
            }else{
                // 找到缺失的元素,更新结果,同时 k 自减 1
                res = i;
                --k;
            }
        }

        return res;
    }
}

二分法

严格升序排列的数组中,截止第i位元素,缺失的元素数量为 arr[i] - i - 1,那么我们可以利用该公式,通过二分法来快速找到对应的索引位置,再计算出其中的差价,加上索引处的元素返回即可。

class Solution {
    public int findKthPositive(int[] arr, int k) {
        // 边界判断
        if(arr[0] > k){
            return k;
        }

        int left = 0, right = arr.length;
        while(left < right){
            // 取得中间点索引
            int mid = left + (right - left) / 2;
            // 套用公式判断是否为目标点
            if(arr[mid] - mid - 1 >= k){
                right = mid;
            }else{
                left = mid + 1;
            }
        }

        // 得到差价,加上索引处元素,返回结果
        return k - (arr[left - 1] - left) + arr[left - 1];
    }
}