一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
给你一个 严格升序排列 的正整数数组 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 <= 10001 <= arr[i] <= 10001 <= k <= 1000- 对于所有
1 <= i < j <= arr.length的i和j满足arr[i] < arr[j]
二分查找
对于每个元素 ,我们都可以唯一确定到第 i 个元素为止缺失的元素数量为 ,例如:
我们发现 是随 i 非严格递增的,于是可以使用二分查找解决这个问题。我们只要找到一个 i 使得 ,就可以确定缺失的第 k 个数为 。也就是说,我们要找到第一个大于等于 k 的 。
在实现的时候,我们要注意两个边界的处理:
- 当 时,最终 ,找不到 ,所以提前判断是否 ,如果是,则直接返回 。
- 当最后一个元素对应的缺失个数 时,我们并不能找到第一个大于等于 的 ,为了解决这个问题,可以在 序列的最后加入一个虚拟的值,这个值的大小为一个不会出现的非常大的数,这样就可以保证一定能找到一个大于等于 的 。
var findKthPositive = function(arr, k) {
if (arr[0] > k) {
return k;
}
let l = 0, r = arr.length;
while (l < r) {
const mid = Math.floor((l + r) / 2);
let x = mid < arr.length ? arr[mid] : 2000000;
if (x - mid - 1 >= k) {
r = mid;
} else {
l = mid + 1;
}
}
return k - (arr[l - 1] - (l - 1) - 1) + arr[l - 1];
};
复杂度分析
- 时间复杂度: ,其中 是数组 的长度。即二分查找的时间复杂度。
- 空间复杂度: 。