🧠
Optimized Approach (Cyclic Sort + Boolean Array for Extra Missing)
💡 This approach improves space usage by using a boolean array instead of a set to track extra numbers beyond the array range, reducing overhead.
Intuition
After cyclic sort, identify missing numbers within the array range. Use a boolean array to mark numbers seen beyond the array range to efficiently find extra missing numbers.
Algorithm
- Perform cyclic sort to place numbers correctly.
- Traverse array to find missing numbers within range and collect them.
- Create a boolean array to mark numbers beyond the array range that appear in the array.
- Iterate from n+1 upwards, adding numbers not marked in boolean array until K missing numbers are found.
💡 This approach reduces overhead of hash sets by using fixed-size boolean arrays, improving performance.
def find_k_missing_numbers(arr, k):
n = len(arr)
i = 0
while i < n:
correct_index = arr[i] - 1
if 1 <= arr[i] <= n and arr[i] != arr[correct_index]:
arr[i], arr[correct_index] = arr[correct_index], arr[i]
else:
i += 1
missing = []
extra_nums = [False] * (k + n + 1)
for i in range(n):
if arr[i] != i + 1 and len(missing) < k:
missing.append(i + 1)
if arr[i] > n and arr[i] < len(extra_nums):
extra_nums[arr[i]] = True
next_num = n + 1
while len(missing) < k:
if next_num >= len(extra_nums) or not extra_nums[next_num]:
missing.append(next_num)
next_num += 1
return missing
# Driver code
if __name__ == '__main__':
print(find_k_missing_numbers([3, -1, 4, 5, 5], 3)) # Output: [1, 2, 6]
Line Notes
extra_nums = [False] * (k + n + 1)Boolean array to track extra numbers beyond array range
if arr[i] != i + 1 and len(missing) < k:Collect missing numbers within array range
if arr[i] > n and arr[i] < len(extra_nums):Mark presence of numbers beyond array range
while len(missing) < k:Add missing numbers beyond array range
import java.util.*;
public class Main {
public static List<Integer> findKMissingNumbers(int[] arr, int k) {
int n = arr.length;
int i = 0;
while (i < n) {
int correctIndex = arr[i] - 1;
if (arr[i] >= 1 && arr[i] <= n && arr[i] != arr[correctIndex]) {
int temp = arr[i];
arr[i] = arr[correctIndex];
arr[correctIndex] = temp;
} else {
i++;
}
}
List<Integer> missing = new ArrayList<>();
boolean[] extraNums = new boolean[k + n + 1];
for (i = 0; i < n; i++) {
if (arr[i] != i + 1 && missing.size() < k) {
missing.add(i + 1);
}
if (arr[i] > n && arr[i] < extraNums.length) {
extraNums[arr[i]] = true;
}
}
int nextNum = n + 1;
while (missing.size() < k) {
if (nextNum >= extraNums.length || !extraNums[nextNum]) {
missing.add(nextNum);
}
nextNum++;
}
return missing;
}
public static void main(String[] args) {
System.out.println(findKMissingNumbers(new int[]{3, -1, 4, 5, 5}, 3)); // [1, 2, 6]
}
}
Line Notes
boolean[] extraNums = new boolean[k + n + 1]Boolean array to track extra numbers beyond array range
if (arr[i] != i + 1 && missing.size() < k)Collect missing numbers within array range
if (arr[i] > n && arr[i] < extraNums.length)Mark presence of numbers beyond array range
while (missing.size() < k)Add missing numbers beyond array range
#include <iostream>
#include <vector>
using namespace std;
vector<int> findKMissingNumbers(vector<int>& arr, int k) {
int n = arr.size();
int i = 0;
while (i < n) {
int correctIndex = arr[i] - 1;
if (arr[i] >= 1 && arr[i] <= n && arr[i] != arr[correctIndex]) {
swap(arr[i], arr[correctIndex]);
} else {
i++;
}
}
vector<int> missing;
vector<bool> extraNums(k + n + 1, false);
for (int i = 0; i < n; i++) {
if (arr[i] != i + 1 && (int)missing.size() < k) {
missing.push_back(i + 1);
}
if (arr[i] > n && arr[i] < (int)extraNums.size()) {
extraNums[arr[i]] = true;
}
}
int nextNum = n + 1;
while ((int)missing.size() < k) {
if (nextNum >= (int)extraNums.size() || !extraNums[nextNum]) {
missing.push_back(nextNum);
}
nextNum++;
}
return missing;
}
int main() {
vector<int> arr = {3, -1, 4, 5, 5};
vector<int> res = findKMissingNumbers(arr, 3);
for (int num : res) cout << num << " ";
cout << endl;
return 0;
}
Line Notes
vector<bool> extraNums(k + n + 1, false)Boolean vector to track extra numbers beyond array range
if (arr[i] != i + 1 && (int)missing.size() < k)Collect missing numbers within array range
if (arr[i] > n && arr[i] < (int)extraNums.size())Mark presence of numbers beyond array range
while ((int)missing.size() < k)Add missing numbers beyond array range
function findKMissingNumbers(arr, k) {
let n = arr.length;
let i = 0;
while (i < n) {
let correctIndex = arr[i] - 1;
if (arr[i] >= 1 && arr[i] <= n && arr[i] !== arr[correctIndex]) {
[arr[i], arr[correctIndex]] = [arr[correctIndex], arr[i]];
} else {
i++;
}
}
const missing = [];
const extraNums = new Array(k + n + 1).fill(false);
for (let i = 0; i < n; i++) {
if (arr[i] !== i + 1 && missing.length < k) {
missing.push(i + 1);
}
if (arr[i] > n && arr[i] < extraNums.length) {
extraNums[arr[i]] = true;
}
}
let nextNum = n + 1;
while (missing.length < k) {
if (nextNum >= extraNums.length || !extraNums[nextNum]) {
missing.push(nextNum);
}
nextNum++;
}
return missing;
}
// Test
console.log(findKMissingNumbers([3, -1, 4, 5, 5], 3)); // [1, 2, 6]
Line Notes
const extraNums = new Array(k + n + 1).fill(false)Boolean array to track extra numbers beyond array range
if (arr[i] !== i + 1 && missing.length < k)Collect missing numbers within array range
if (arr[i] > n && arr[i] < extraNums.length)Mark presence of numbers beyond array range
while (missing.length < k)Add missing numbers beyond array range
TimeO(n + k)
SpaceO(n + k) due to boolean array
Cyclic sort is O(n), scanning is O(n), and adding missing numbers is O(k). Boolean array uses less overhead than a set.
💡 This approach is the most efficient and practical for large inputs in interviews.
Interview Verdict: Accepted and optimal for large inputs
This is the best approach to implement in interviews for this problem.