🧠
Optimal Cyclic Sort Approach
💡 Cyclic sort leverages the fact that numbers are from 1 to n and places each number at its correct index. This approach finds the duplicate and missing in one pass without extra space.
Intuition
Place each number at its correct index (num-1). If a number is already at the correct index, it must be a duplicate. After placement, the index where the number is incorrect indicates the missing number.
Algorithm
- Initialize index i = 0.
- While i < n, if nums[i] != i + 1 and nums[i] != nums[nums[i] - 1], swap nums[i] with nums[nums[i] - 1].
- Else, increment i.
- After sorting, traverse the array to find the index where nums[i] != i + 1.
- The number at that index is the duplicate, and i + 1 is the missing number.
- Return [duplicate, missing].
💡 The cyclic sort places numbers in correct positions, revealing the duplicate and missing by mismatch.
def find_duplicate_missing(nums):
i = 0
n = len(nums)
while i < n:
correct_index = nums[i] - 1
if nums[i] != nums[correct_index]:
nums[i], nums[correct_index] = nums[correct_index], nums[i]
else:
i += 1
for i in range(n):
if nums[i] != i + 1:
return [nums[i], i + 1]
return [-1, -1]
# Driver code
if __name__ == '__main__':
print(find_duplicate_missing([3, 1, 2, 5, 3])) # Output: [3, 4]
Line Notes
i = 0Start index for cyclic sort
correct_index = nums[i] - 1Calculate correct position for current number
if nums[i] != nums[correct_index]:Check if current number is at correct position or duplicate
nums[i], nums[correct_index] = nums[correct_index], nums[i]Swap to place number correctly
else:If no swap needed, move to next index
i += 1Increment index when no swap
for i in range(n):After sorting, find mismatch
if nums[i] != i + 1:Mismatch indicates duplicate and missing
return [nums[i], i + 1]Return duplicate and missing
public class Solution {
public static int[] findDuplicateMissing(int[] nums) {
int i = 0, n = nums.length;
while (i < n) {
int correctIndex = nums[i] - 1;
if (nums[i] != nums[correctIndex]) {
int temp = nums[i];
nums[i] = nums[correctIndex];
nums[correctIndex] = temp;
} else {
i++;
}
}
for (i = 0; i < n; i++) {
if (nums[i] != i + 1) {
return new int[]{nums[i], i + 1};
}
}
return new int[]{-1, -1};
}
public static void main(String[] args) {
int[] nums = {3, 1, 2, 5, 3};
int[] res = findDuplicateMissing(nums);
System.out.println(java.util.Arrays.toString(res)); // [3, 4]
}
}
Line Notes
int i = 0, n = nums.length;Initialize index and length
int correctIndex = nums[i] - 1;Calculate correct index for current number
if (nums[i] != nums[correctIndex]) {Check if swap needed
swap nums[i] and nums[correctIndex]Place number at correct index
else {If no swap needed, move to next index
i++;Increment index when no swap
for (i = 0; i < n; i++) {Find mismatch after sorting
if (nums[i] != i + 1)Mismatch indicates duplicate and missing
return new int[]{nums[i], i + 1};Return result
#include <iostream>
#include <vector>
using namespace std;
vector<int> findDuplicateMissing(vector<int>& nums) {
int i = 0, n = nums.size();
while (i < n) {
int correctIndex = nums[i] - 1;
if (nums[i] != nums[correctIndex]) {
swap(nums[i], nums[correctIndex]);
} else {
i++;
}
}
for (int i = 0; i < n; i++) {
if (nums[i] != i + 1) {
return {nums[i], i + 1};
}
}
return {-1, -1};
}
int main() {
vector<int> nums = {3, 1, 2, 5, 3};
vector<int> res = findDuplicateMissing(nums);
cout << "[" << res[0] << ", " << res[1] << "]" << endl; // [3, 4]
return 0;
}
Line Notes
int i = 0, n = nums.size();Initialize index and array size
int correctIndex = nums[i] - 1;Calculate correct index for current number
if (nums[i] != nums[correctIndex]) {Check if swap needed
swap(nums[i], nums[correctIndex]);Place number at correct index
else {If no swap needed, move to next index
i++;Increment index when no swap
for (int i = 0; i < n; i++) {Find mismatch after sorting
if (nums[i] != i + 1)Mismatch indicates duplicate and missing
return {nums[i], i + 1};Return result
function findDuplicateMissing(nums) {
let i = 0, n = nums.length;
while (i < n) {
let correctIndex = nums[i] - 1;
if (nums[i] !== nums[correctIndex]) {
[nums[i], nums[correctIndex]] = [nums[correctIndex], nums[i]];
} else {
i++;
}
}
for (let i = 0; i < n; i++) {
if (nums[i] !== i + 1) {
return [nums[i], i + 1];
}
}
return [-1, -1];
}
// Test
console.log(findDuplicateMissing([3, 1, 2, 5, 3])); // [3, 4]
Line Notes
let i = 0, n = nums.length;Initialize index and length
let correctIndex = nums[i] - 1;Calculate correct index for current number
if (nums[i] !== nums[correctIndex]) {Check if swap needed
[nums[i], nums[correctIndex]] = [nums[correctIndex], nums[i]];Swap to place number correctly
else {If no swap needed, move to next index
i++;Increment index when no swap
for (let i = 0; i < n; i++) {Find mismatch after sorting
if (nums[i] !== i + 1)Mismatch indicates duplicate and missing
return [nums[i], i + 1];Return result
Each number is swapped at most once to its correct position, so total operations are linear. No extra space is used besides variables.
💡 For n=1000, this means roughly 1000 operations, very efficient for large inputs.
Interview Verdict: Accepted and optimal
This is the best approach to implement in interviews for this problem.