LeetCode 1060 - Missing Element in Sorted Array
The problem asks us to find the k-th missing number in a sorted, strictly increasing array of unique integers. Given nums and an integer k, we need to identify the number that is missing from the sequence formed by consecutive integers starting from nums[0].
Difficulty: 🟡 Medium
Topics: Array, Binary Search
Solution
Problem Understanding
The problem asks us to find the k-th missing number in a sorted, strictly increasing array of unique integers. Given nums and an integer k, we need to identify the number that is missing from the sequence formed by consecutive integers starting from nums[0].
The input nums represents known elements in a sorted sequence, but some integers between nums[0] and nums[-1] (and potentially beyond) are missing. The integer k specifies which missing number to return, counting from the first missing number in order.
The output is a single integer, the k-th missing number. Constraints guarantee that the array can be fairly large (up to 5 * 10^4) and k can also be very large (up to 10^8). This implies that naive linear solutions that check each number sequentially will be too slow for large input ranges.
Key observations include that the array is strictly increasing, so the number of missing elements between two consecutive elements can be calculated as nums[i+1] - nums[i] - 1. Edge cases include situations where the missing number is before the first array element, after the last array element, or exactly between two elements.
Approaches
The brute-force approach iterates through every integer starting from nums[0], counting missing numbers until we reach the k-th missing one. This approach is guaranteed to work but is inefficient. If nums[-1] is very large and k is also large, it may require checking millions of numbers, leading to a time complexity of O(N + k), which is not feasible for the upper constraint bounds.
The optimal approach leverages the fact that the array is sorted. We can compute the number of missing elements up to any index i using nums[i] - nums[0] - i. This gives us a strictly increasing function representing cumulative missing counts. Since it is monotonic, we can perform a binary search to efficiently find the first index where the cumulative number of missing numbers is at least k. Once the proper interval is found, the k-th missing number can be computed directly. This reduces the time complexity to O(log N) and uses O(1) extra space.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(k + n) | O(1) | Iterate sequentially counting missing numbers |
| Optimal | O(log n) | O(1) | Binary search using cumulative missing numbers formula |
Algorithm Walkthrough
- Calculate missing numbers at index i: Define a helper function
missing(i)that computes the total number of missing numbers fromnums[0]tonums[i]using the formulanums[i] - nums[0] - i. - Check if k-th missing number is beyond the last element: If
k > missing(n-1), then the k-th missing number is afternums[-1]and can be calculated asnums[-1] + (k - missing(n-1)). - Perform binary search: Initialize
leftas 0 andrightasn - 1. Perform standard binary search to find the first indexidxsuch thatmissing(idx) >= k. In each iteration, calculatemid = (left + right) // 2. Ifmissing(mid) < k, movelefttomid + 1; otherwise, moverighttomid. - Calculate the k-th missing number: After binary search,
leftpoints to the first index where cumulative missing numbers are greater than or equal tok. The k-th missing number can be calculated asnums[left - 1] + (k - missing(left - 1)).
Why it works: The cumulative missing count is strictly increasing, so the binary search guarantees that we find the correct interval where the k-th missing number falls. Using the formula nums[i] - nums[0] - i ensures that the computation of missing numbers is accurate and monotonic.
Python Solution
from typing import List
class Solution:
def missingElement(self, nums: List[int], k: int) -> int:
n = len(nums)
# Helper function to compute missing numbers until index i
def missing(index: int) -> int:
return nums[index] - nums[0] - index
# If k-th missing is beyond the last element
if k > missing(n - 1):
return nums[-1] + (k - missing(n - 1))
left, right = 0, n - 1
while left < right:
mid = (left + right) // 2
if missing(mid) < k:
left = mid + 1
else:
right = mid
# k-th missing number is between nums[left - 1] and nums[left]
return nums[left - 1] + (k - missing(left - 1))
This implementation first checks if the k-th missing number lies beyond the last element. If not, it performs binary search on the cumulative missing numbers. The helper function ensures clear and correct computation of the missing count. The final calculation adjusts from the previous known element to reach the k-th missing number.
Go Solution
func missingElement(nums []int, k int) int {
n := len(nums)
// Helper function to calculate missing numbers until index i
missing := func(index int) int {
return nums[index] - nums[0] - index
}
// If k-th missing is beyond the last element
if k > missing(n - 1) {
return nums[n - 1] + (k - missing(n - 1))
}
left, right := 0, n - 1
for left < right {
mid := (left + right) / 2
if missing(mid) < k {
left = mid + 1
} else {
right = mid
}
}
return nums[left - 1] + (k - missing(left - 1))
}
The Go implementation mirrors the Python logic. Differences include using an inline function for the missing calculation and integer division with /. Slices handle dynamic lengths naturally. Overflow is not an issue under the problem constraints.
Worked Examples
Example 1: nums = [4,7,9,10], k = 1
| Step | left | right | mid | missing(mid) | Action |
|---|---|---|---|---|---|
| 1 | 0 | 3 | 1 | 2 | missing(1) >= k → right = 1 |
| 2 | 0 | 1 | 0 | 0 | missing(0) < k → left = 1 |
k-th missing = nums[0] + (1 - missing(0)) = 4 + 1 = 5
Example 2: nums = [4,7,9,10], k = 3
| Step | left | right | mid | missing(mid) | Action |
|---|---|---|---|---|---|
| 1 | 0 | 3 | 1 | 2 | missing(1) < k → left = 2 |
| 2 | 2 | 3 | 2 | 4 | missing(2) >= k → right = 2 |
k-th missing = nums[1] + (3 - missing(1)) = 7 + (3-2) = 8
Example 3: nums = [1,2,4], k = 3
| Step | left | right | mid | missing(mid) | Action |
|---|---|---|---|---|---|
| 1 | 0 | 2 | 1 | 0 | missing(1) < k → left = 2 |
k-th missing = nums[1] + (3 - missing(1)) = 2 + (3-0) = 5 → wait correction: missing(1) = nums[1]-nums[0]-1=2-1-1=0, then 3-0=3, nums[1]+3=2+3=5. Correct, but the missing numbers are [3,5,6], 3rd missing=6 → must be careful: nums[left-1]=2, k - missing(left-1)=3-0=3 → 2+3=5 → hmm, missing numbers counting from nums[0]?
Check: missing(i)=nums[i]-nums[0]-i: missing(0)=1-1-0=0, missing(1)=2-1-1=0, missing(2)=4-1-2=1 → total missing up to last index=1, k=3>1 → return nums[-1]+(3-1)=4+2=6, correct. Yes, works.)
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(log n) | Binary search on the array of length n |
| Space | O(1) | Constant extra space; only indices and helper function |
This is efficient because the cumulative missing numbers function is strictly increasing, allowing logarithmic search instead of linear iteration.
Test Cases
# Provided examples
assert Solution().