给出一个有序数组 A
,数组中的每个数字都是 独一无二的,找出从数组最左边开始的第 K
个缺失数字。
示例 1:
输入:A = [4,7,9,10], K = 1
输出:5
解释:
第一个缺失数字为 5 。
示例 2:
输入:A = [4,7,9,10], K = 3
输出:8
解释:
缺失数字有 [5,6,8,...],因此第三个缺失数字为 8 。
示例 3:
输入:A = [1,2,4], K = 3
输出:6
解释:
缺失数字有 [3,5,6,7,...],因此第三个缺失数字为 6 。
提示:
1 <= A.length <= 50000
1 <= A[i] <= 1e7
1 <= K <=
1e8
题解与思路
思路
由于数组是有序的,我们可以通过比较数组中的元素和它们的索引来确定缺失了多少个数字。具体来说,对于数组中的每个元素A[i]A[i],在位置ii上,如果没有缺失任何数字,那么A[i] = i + 1 + A[0] - 1 A[i]=i+1+A[0]−1。这里,A[0] - 1A[0]−1是初始偏移量,因为数组不一定从1开始。因此,对于任何位置ii,到这个位置为止缺失的数字数量应该是A[i] - i - 1 - (A[0] - 1)A[i]−i−1−(A[0]−1)。
我们可以利用这个关系进行二分查找:
- 计算中间位置midmid的缺失数字数量。
- 如果缺失数量小于KK,说明第KK个缺失的数字在右侧,我们向右二分。
- 如果缺失数量大于或等于KK,说明第KK个缺失的数字在左侧或就是当前位置,我们向左二分。
- 当我们缩小到某个点时,根据KK和左侧缺失数量的差值,我们可以直接计算出确切的缺失数字。
/*
* 题解
* 由于数组是有序的,我们可以通过比较数组中的元素和它们的索引来确定缺失了多少个数字。具体来说,对于数组中的每个元素A[i],在位置i上,如果没有缺失任何数字,那么A[i]=i+1+A[0]-1。这里,A[0] - 1是初始偏移量,因为数组不一定从1开始。因此,对于任何位置i,到这个位置为止缺失的数字数量应该是A[i] - i - 1 - (A[0] - 1)。
*
* 我们可以利用这个关系进行二分查找:
*
* 计算中间位置midmid的缺失数字数量。
* 如果缺失数量小于KK,说明第KK个缺失的数字在右侧,我们向右二分。
* 如果缺失数量大于或等于KK,说明第KK个缺失的数字在左侧或就是当前位置,我们向左二分。
* 当我们缩小到某个点时,根据KK和左侧缺失数量的差值,我们可以直接计算出确切的缺失数字。
*/
public class Solution{
public static int missingElement(int[] nums, int k) {
int n = nums.length;
int left = 0, right = n - 1;
// 如果k大于数组末尾缺失的数量,则直接计算并返回
//具体逻辑 我以A[0]是参照物 然后我去算 如果没有任何缺数的情况 那么我这个末尾应该是多少
// 然后用实际的去减去应该的即是我们这边一共插了多少个
int missingNums = nums[n - 1] - nums[0] + 1 - n;
if (k > missingNums) {
return nums[n - 1] + k - missingNums;
}
// 二分查找
while (left < right) {
int mid = left + (right - left) / 2;
missingNums = nums[mid] - nums[0] - mid;
if (missingNums < k) {
// 缺失的数字在右侧
left = mid + 1;
} else {
// 缺失的数字在左侧或当前位置
right = mid;
}
}
// 计算第K个缺失数字
return nums[left - 1] + k - (nums[left - 1] - nums[0] - (left - 1));
}
public static void main(String[] args) {
int [] arr=new int[10];
arr= new int[]{1, 3, 4, 7, 10};
System.out.println(missingElement(arr, 400));
}
}
/*
* 我们通过二分查找确定第KK个缺失数字的大致位置。
* 二分查找的终止条件是left < right,最终left和right会相遇,在这个点左侧的缺失数量加上KK可以直接计算出第KK个缺失的数字。
* 注意,由于我们的计算方法,需要在最后的计算中考虑到左侧边界,即nums[left - 1],这是因为我们的left和right最终会停在缺失数字应当插入的位置。
*/
- 我们通过二分查找确定第KK个缺失数字的大致位置。
- 二分查找的终止条件是
left < right
,最终left
和right
会相遇,在这个点左侧的缺失数量加上KK可以直接计算出第KK个缺失的数字。 - 注意,由于我们的计算方法,需要在最后的计算中考虑到左侧边界,即
nums[left - 1]
,这是因为我们的left
和right
最终会停在缺失数字应当插入的位置。 - 这个题目感觉还行 一起加油啦 大家