文章目录
- 一【题目类别】
- 二【题目难度】
- 三【题目编号】
- 四【题目描述】
- 五【题目示例】
- 六【解题思路】
- 七【题目提示】
- 八【题目进阶】
- 九【时间频度】
- 十【代码实现】
- 十一【提交结果】
一【题目类别】
- 二分查找
二【题目难度】
- 简单
三【题目编号】
- 1539.第 k 个缺失的正整数
四【题目描述】
- 给你一个 严格升序排列 的正整数数组 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 。
六【解题思路】
- 利用二分查找的思想,不过找的不是目标值,而是缺失数字数量大于k的最小位置
- 那么如何计算每个位置的缺失数字数量呢?可以用公式: a r r [ m i d ] − m i d − 1 arr[mid] - mid - 1 arr[mid]−mid−1计算,其中 m i d mid mid就是二分查找的中间值
- 如果缺失数字数量大于或等于 k k k,说明需要向左查找,反之需要向右查找
- 当找到缺失数字数量大于 k k k的最小位置后(用 l e f t left left表示),就可以计算第 k k k个缺失的数字了
- 用 a r r [ l e f t − 1 ] − ( l e f t − 1 ) − 1 arr[left - 1] - (left - 1) - 1 arr[left−1]−(left−1)−1表示找到的位置缺失的数字数量, k − ( a r r [ l e f t − 1 ] − ( l e f t − 1 ) − 1 ) k - (arr[left - 1] - (left - 1) - 1) k−(arr[left−1]−(left−1)−1)就表示从 a r r [ l e f t − 1 ] arr[left - 1] arr[left−1]开始还缺几个数字,最后再加上 a r r [ l e f t − 1 ] arr[left - 1] arr[left−1]就是第 k k k个缺失的数字,这里 l e f t left left减一就是缺失数字数量和大于 k k k的最小位置,所以最后的计算公式就是 k − ( a r r [ l e f t − 1 ] − ( l e f t − 1 ) − 1 ) + a r r [ l e f t − 1 ] k - (arr[left - 1] - (left - 1) - 1) + arr[left - 1] k−(arr[left−1]−(left−1)−1)+arr[left−1]
- 另外还需要注意边界条件,如果数组的第一个数字都大于 k k k,说明第 k k k个缺失的数字就是 k k k,直接返回 k k k就行
- 最后返回结果即可
七【题目提示】
- 1 < = a r r . l e n g t h < = 1000 1 <= arr.length <= 1000 1<=arr.length<=1000
- 1 < = a r r [ i ] < = 1000 1 <= arr[i] <= 1000 1<=arr[i]<=1000
- 1 < = k < = 1000 1 <= k <= 1000 1<=k<=1000
- 对于所有 1 < = i < j < = a r r . l e n g t h 的 i 和 j 满足 a r r [ i ] < a r r [ j ] 对于所有 1 <= i < j <= arr.length 的 i 和 j 满足 arr[i] < arr[j] 对于所有1<=i<j<=arr.length的i和j满足arr[i]<arr[j]
八【题目进阶】
- 你可以设计一个时间复杂度小于 O(n) 的算法解决此问题吗?
九【时间频度】
- 时间复杂度: O ( l o g n ) O(logn) O(logn),其中 n n n为数组的长度
- 空间复杂度: O ( 1 ) O(1) O(1)
十【代码实现】
- Java语言版
class Solution {
public int findKthPositive(int[] arr, int k) {
if(arr[0] > k){
return k;
}
int left = 0;
int right = arr.length;
while(left < right){
int mid = (left + right) / 2;
int dif = arr[mid] - mid - 1;
if(dif >= k){
right = mid;
}else{
left = mid + 1;
}
}
return k - (arr[left - 1] - (left - 1) - 1) + arr[left - 1];
}
}
- C语言版
int findKthPositive(int* arr, int arrSize, int k)
{
if(arr[0] > k)
{
return k;
}
int left = 0;
int right = arrSize;
while(left < right)
{
int mid = (left + right) / 2;
int dif = arr[mid] - mid - 1;
if(dif >= k)
{
right = mid;
}
else
{
left = mid + 1;
}
}
return k - (arr[left - 1] - (left - 1) - 1) + arr[left - 1];
}
- Python版
class Solution:
def findKthPositive(self, arr: List[int], k: int) -> int:
if arr[0] > k:
return k
left = 0
right = len(arr)
while left < right:
mid = (left + right) // 2
dif = arr[mid] - mid - 1
if dif >= k:
right = mid
else:
left = mid + 1
return k - (arr[left - 1] - (left - 1) - 1) + arr[left - 1]
十一【提交结果】
-
Java语言版
-
C语言版
-
Python语言版