题目描述
给你一个 严格升序排列 的正整数数组 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 a0 | 2 | 1 |
a 1 a_1 a1 | 3 | 1 |
a 2 a_2 a2 | 4 | 1 |
a 3 a_3 a3 | 7 | 3 |
a 4 a_4 a4 | 11 | 6 |
不难发现,
p
i
p_i
pi 是随 i 非严格递增的,所以可以二分查找解决这道题目。
只要找到一个 i 使用
p
i
−
1
<
k
<
=
p
i
p_{i - 1} < k <= p_i
pi−1<k<=pi,就可以确定缺失的第 k 个正整数为
k
−
p
i
−
1
k - p_{i - 1}
k−pi−1 + 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)。