Easy
题目描述
给你一个 严格升序排列 的正整数数组 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,有arr[i] < arr[j]
进阶: 你可以设计一个时间复杂度小于 O(n) 的算法来解决此问题吗?
解题思路
解题思路
这道题要求找到数组中第 k 个缺失的正整数。我们可以用两种方法来解决:
方法一:线性扫描(推荐)
最直观的思路是遍历数组,同时维护一个期望值 expected,表示当前位置应该出现的正整数。如果当前数组元素等于期望值,说明没有缺失;否则说明有缺失的数字,我们需要统计缺失的个数。
具体步骤:
- 初始化期望值为 1,缺失计数为 0
- 遍历数组,对于每个元素,计算它前面缺失了多少个正整数
- 如果缺失数量达到 k,直接返回对应的缺失数字
- 如果遍历完数组还没找到,说明第 k 个缺失数字在数组最后一个元素之后
方法二:二分查找
对于进阶要求,我们可以使用二分查找。关键观察是:对于数组中位置 i 的元素 arr[i],在它之前缺失的正整数个数为 arr[i] - (i + 1)。我们可以二分查找第一个缺失数量大于等于 k 的位置。
时间复杂度:线性扫描 O(n),二分查找 O(log n)
代码实现
class Solution {
public:
int findKthPositive(vector<int>& arr, int k) {
int expected = 1;
int missing = 0;
for (int num : arr) {
missing += num - expected;
if (missing >= k) {
return num - (missing - k + 1);
}
expected = num + 1;
}
return arr.back() + (k - missing);
}
};
class Solution:
def findKthPositive(self, arr: List[int], k: int) -> int:
expected = 1
missing = 0
for num in arr:
missing += num - expected
if missing >= k:
return num - (missing - k + 1)
expected = num + 1
return arr[-1] + (k - missing)
public class Solution {
public int FindKthPositive(int[] arr, int k) {
int expected = 1;
int missing = 0;
foreach (int num in arr) {
missing += num - expected;
if (missing >= k) {
return num - (missing - k + 1);
}
expected = num + 1;
}
return arr[arr.Length - 1] + (k - missing);
}
}
var findKthPositive = function(arr, k) {
let expected = 1;
let missing = 0;
for (let num of arr) {
missing += num - expected;
if (missing >= k) {
return num - (missing - k + 1);
}
expected = num + 1;
}
return arr[arr.length - 1] + (k - missing);
};
复杂度分析
| 方法 | 时间复杂度 | 空间复杂度 |
|---|---|---|
| 线性扫描 | O(n) | O(1) |
| 二分查找 | O(log n) | O(1) |
相关题目
- . Append K Integers With Minimal Sum (Medium)