一起养成写作习惯!这是我参与「掘金日新计划 · 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 <= 10001 <= arr[i] <= 10001 <= 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];
}
}