https://leetcode.com/problems/missing-element-in-sorted-array/
It should be easy to come up with the idea of binary search but may be challenging to reason the correctness of an implementation.
Let lo
and hi
be the starting and end indicies indicating the range for binary search.
Property: the total count of missing numbers between lo
and hi
is (nums[hi] - nums[lo]) - (hi - lo)
.
- Explain:
nums[hi] - nums[lo] + 1
is the total count of numbers in the range[lo .. hi]
andhi - lo + 1
is the count of numbers existing in that range. - Example: Given
nums = [3, 5, 7]
,lo = 0
andhi = 2
. Count of missing numbers in this range is7 - 3 - (2 - 0) = 2
, which is4
and6
.
By appending inf
to the end of the array, we can maintain an invariant through out binary search: missing number n
must be in the range between lo
and hi
. i.e. nums[lo] < n < nums[hi]
- Base case: initially,
nums[hi] = inf
so the invariant holds. - Inductive step: let
mid = (lo + hi) // 2
and the count of missing numbers in the range[lo .. mid]
bem
, which is(nums[mid] - nums[lo]) - (mid - lo)
according to the property above. We will updatelo
,hi
andk
on each step of binary search.- if
m >= k
,n
must be thek
th missing number in the range[lo .. mid]
; - Otherwise,
n
must be thek - m
th missing number in the range[mid .. hi]
. (update withk' = k - m
)
- if
- Termination condition: when
lo = hi - 1
, the search terminates andn
will be thek
-th number afternums[lo]
.
class Solution:
def missingElement(self, nums: List[int], k: int) -> int:
nums.append(inf)
lo = 0
hi = len(nums) - 1
while lo < hi - 1:
mid = (lo + hi) // 2
missing = nums[mid] - nums[lo] - (mid - lo)
if missing >= k:
hi = mid
else:
lo = mid
k -= missing
return nums[lo] + k