Problem Statement
Given a sorted arrayarr
of distinct positive integers and a positive integer k
, return the kth missing positive integer that is missing from this sequence.
The missing numbers are the positive integers that do not appear in arr
but are smaller than or equal to the maximum value reached by adding k
missing numbers.
Examples
Example 1:
Input: arr = [2, 3, 4, 7, 11], k = 5
Output: 9
Explanation: The missing numbers are [1, 5, 6, 8, 9, 10, ...]
The 5th missing number is 9.
Example 2:
Input: arr = [1, 2, 3, 4], k = 2
Output: 6
Explanation: The array contains no gaps until 4. The first missing number is 5, and the second missing number is 6.
Example 3:
Input: arr = [3, 6, 8, 10], k = 4
Output: 7
Explanation: The missing numbers are [1, 2, 4, 5, 7, 9...]
The 4th missing number is 7
Different Approaches
1️⃣ Brute Force Approach
Intuition:
The problem revolves around finding the kth
missing positive integer. Since arr
is sorted and strictly increasing, the missing numbers between any two consecutive elements can be deduced. By iterating through the array and keeping track of the count of missing numbers, we can determine when the kth
missing number is encountered.
Approach:
- Start from
1
(the smallest positive integer). - Iterate through each number and check if it exists in the array:
- If it does, skip it.
- If it does not, count it as a "missing number."
- Stop when
k
missing numbers are found.
This method effectively simulates the sequence of all positive integers and checks each one against the array.
Dry Run:
For arr = [2, 3, 4, 7, 11]
and k = 5
:
- Start with
current = 1
. It is missing (missingCount = 1
). current = 2
. It exists in the array.current = 3
. It exists in the array.current = 4
. It exists in the array.current = 5
. It is missing (missingCount = 2
).current = 6
. It is missing (missingCount = 3
).current = 7
. It exists in the array.current = 8
. It is missing (missingCount = 4
).current = 9
. It is missing (missingCount = 5
).
The 5th missing number is 9
.
Code:
#include <iostream>
#include <vector>
using namespace std;
int findKthMissing(vector<int>& arr, int k) {
int missingCount = 0; // Counter for missing numbers
int current = 1; // Start from the smallest positive integer
int i = 0; // Index in the array
// Continue until we've found the kth missing number
while (true) {
if (i < arr.size() && arr[i] == current) {
// If the current number is in the array, skip it
i++;
} else {
// If the current number is missing, count it
missingCount++;
if (missingCount == k) {
return current; // Return the kth missing number
}
}
current++; // Move to the next number
}
}
int main() {
vector<int> arr = {2, 3, 4, 7, 11};
int k = 5;
cout << "The " << k << "th missing number is: " << findKthMissing(arr, k) << endl;
return 0;
}
Complexity Analysis:
- Time Complexity:
- In the worst case, we iterate up to the
kth
missing number. - Each iteration involves checking whether the
current
number exists in the array (O(n)
operation in the worst case for each lookup). - Overall, the time complexity is O(k × n).
- In the worst case, we iterate up to the
- Space Complexity:
- No additional space is used apart from variables; hence it is O(1).
2️⃣ Binary Search
Intuition:
We can't apply classical binary search to it.
We can't apply binary search on answers as well because it is applicable when we are looking for minimum or maximum.
The sorted nature of the array suggests using binary search to optimize the solution. Instead of checking each number linearly, we focus on the count of missing numbers up to each index in the array.
For any arr[i]
, the count of missing numbers up to arr[i]
is:
missing_count[i] = arr[i] - (i + 1)
This formula works because arr[i]
includes the value at i
, and (i + 1)
represents the number of positive integers present up to arr[i]
if no numbers were missing.
Using binary search, we:
- Find the first position in the array where the missing count becomes greater than or equal to k.
- The k-th missing number lies outside the current range or between the elements where the missing count changes.
Approach:
- Calculate the missing count for midpoints during the binary search.
- If the missing count at
arr[mid]
is less thank
, the kkk -th missing number lies to the right. - Otherwise, it lies to the left.
- Use the binary search result to calculate the exact kkk -th missing number.
Code:
#include <iostream>
#include <vector>
using namespace std;
int findKthMissing(vector<int>& arr, int k) {
int left = 0, right = arr.size() - 1;
// Perform binary search
while (left <= right) {
int mid = left + (right - left) / 2;
int missingCount = arr[mid] - (mid + 1);
if (missingCount < k) {
left = mid + 1; // Move right
} else {
right = mid - 1; // Move left
}
}
// At the end of the binary search, left points to the smallest index where missingCount >= k
// Calculate the kth missing number
return k + left;
}
int main() {
vector<int> arr = {2, 3, 4, 7, 11};
int k = 5;
cout << "The " << k << "th missing number is: " << findKthMissing(arr, k) << endl;
return 0;
}
Complexity Analysis:
- Time Complexity:
O(log n)
- Space Complexity:
O(1)