[LeetCode] 1060. Missing Element in Sorted Array
Given an integer array nums
which is sorted in ascending order and all of its elements are unique and given also an integer k
, return the kth
missing number starting from the leftmost number of the array.
Example 1:
Input: nums = [4,7,9,10], k = 1 Output: 5 Explanation: The first missing number is 5.
Example 2:
Input: nums = [4,7,9,10], k = 3 Output: 8 Explanation: The missing numbers are [5,6,8,...], hence the third missing number is 8.
Example 3:
Input: nums = [1,2,4], k = 3 Output: 6 Explanation: The missing numbers are [3,5,6,7,...], hence the third missing number is 6.
Constraints:
1 <= nums.length <= 5 * 104
1 <= nums[i] <= 107
nums
is sorted in ascending order, and all the elements are unique.1 <= k <= 108
Follow up: Can you find a logarithmic time complexity (i.e., O(log(n))
) solution?
有序数组中的缺失元素。
给你一个 严格升序排列 的正整数数组 arr
和一个整数 k
。请你找到这个数组里第 k
个缺失的正整数。
这道题有两种思路,一种线性,一种二分法。需要注意一个 corner case,如果 K 大于数组的长度了,那么第 K 个缺失的元素是最后一个元素 + K。同时,missing number 的个数 = nums[end] - nums[start] - (end - start)。举例,4和7之间缺失2个数字 = (7 - 4) - (1 - 0)。
A = [4,7,9,10], K = 3
首先是线性的做法。因为数组是有序的且递增的,所以每次只要计算一下每两个数字之间的差值 - 1就知道是否到 K 了。
一开始 7 - 4 = 3,虽然两个数字的差值是 3,但是实际缺失的数字只有 2 个,所以要减一。如果每两个数字之间的差值小于 K,则需要将 K 减去两数字之间的差值之后,再带入下两个数字之间去比较。反之如果某两个数字之间的差值小于当前的 K,那么第 K 个缺失的数字 = nums[i - 1] + K。
时间O(n)
空间O(1)
Java实现
1 class Solution { 2 public int missingElement(int[] nums, int k) { 3 for (int i = 1; i < nums.length; i++) { 4 if (nums[i] - nums[i - 1] - 1 >= k) { 5 return nums[i - 1] + k; 6 } 7 k -= nums[i] - nums[i - 1] - 1; 8 } 9 return nums[nums.length - 1] + k; 10 } 11 }
再来是二分法。以后看到 input 是有序的,就要想想能不能往二分法上靠,以减小时间复杂度。
因为缺失数字的个数 missing = nums[end] - nums[start] - (end - start),所以如果 K > missing,也就是说如果数组中缺失的数字个数小于 K 的话,结果是 nums[end] + (k - missing)。如果是一般的情形,即缺失的数字夹在数组中间的话,那么我们就用二分法去找。这里的二分,看的是数组中间那个元素 nums[mid] 跟 nums[start] 元素之间有多少个缺失的元素,如果这个差值小于 K,说明要找的数字在数组的右半边,start = mid;反之如果 nums[mid] 跟 nums[start] 之间缺失元素的个数大于 K,则说明第 K 个缺失的数字在数组的左半边。
时间O(logn)
空间O(1)
Java实现
1 class Solution { 2 public int missingElement(int[] nums, int k) { 3 int start = 0; 4 int end = nums.length - 1; 5 int missing = nums[end] - nums[start] - (end - start); 6 // corner case 7 if (k > missing) { 8 return nums[end] + (k - missing); 9 } 10 11 // normal case 12 while (start + 1 < end) { 13 int mid = start + (end - start) / 2; 14 missing = nums[mid] - nums[start] - (mid - start); 15 if (missing < k) { 16 k -= missing; 17 start = mid; 18 } else { 19 end = mid; 20 } 21 } 22 return nums[start] + k; 23 } 24 }
相关题目
410. Split Array Largest Sum
774. Minimize Max Distance to Gas Station
1011. Capacity To Ship Packages In N Days
1060. Missing Element in Sorted Array
1231. Divide Chocolate
1283. Find the Smallest Divisor Given a Threshold
1482. Minimum Number of Days to Make m Bouquets