🧠
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 is optimal in time and space and is a must-know pattern for similar problems.
Intuition
Place each number at the index equal to number-1 by swapping. After this, the index where the number is incorrect reveals the duplicate and missing numbers.
Algorithm
- Initialize index i = 0.
- While i < n, if nums[i] != nums[nums[i] - 1], swap nums[i] with nums[nums[i] - 1], else increment i.
- After sorting, iterate over nums to find the index where nums[i] != i + 1.
- Return [nums[i], i + 1] as duplicate and missing numbers.
💡 The swapping ensures each number is at its correct position. The mismatch after sorting directly gives the answer.
def findErrorNums(nums):
i = 0
n = len(nums)
while i < n:
correct = nums[i] - 1
if nums[i] != nums[correct]:
nums[i], nums[correct] = nums[correct], 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(findErrorNums([1, 2, 2, 4])) # Output: [2, 3]
Line Notes
while i < n:Loop through array to place numbers correctly
correct = nums[i] - 1Calculate correct index for current number
if nums[i] != nums[correct]:Check if current number is at correct position
nums[i], nums[correct] = nums[correct], nums[i]Swap to place number correctly
public class Solution {
public static int[] findErrorNums(int[] nums) {
int i = 0, n = nums.length;
while (i < n) {
int correct = nums[i] - 1;
if (nums[i] != nums[correct]) {
int temp = nums[i];
nums[i] = nums[correct];
nums[correct] = 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[] result = findErrorNums(new int[]{1, 2, 2, 4});
System.out.println(java.util.Arrays.toString(result)); // Output: [2, 3]
}
}
Line Notes
while (i < n)Iterate to place each number at correct index
int correct = nums[i] - 1;Calculate target index for current number
if (nums[i] != nums[correct])Check if swap is needed
nums[i] = nums[correct]; nums[correct] = temp;Swap numbers to correct positions
#include <iostream>
#include <vector>
using namespace std;
vector<int> findErrorNums(vector<int>& nums) {
int i = 0, n = nums.size();
while (i < n) {
int correct = nums[i] - 1;
if (nums[i] != nums[correct]) {
swap(nums[i], nums[correct]);
} 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 = {1, 2, 2, 4};
vector<int> result = findErrorNums(nums);
cout << "[" << result[0] << ", " << result[1] << "]" << endl; // Output: [2, 3]
return 0;
}
Line Notes
while (i < n)Loop to place each number at its correct index
int correct = nums[i] - 1;Calculate correct index for current number
if (nums[i] != nums[correct])Check if current number is misplaced
swap(nums[i], nums[correct]);Swap to correct position
function findErrorNums(nums) {
let i = 0, n = nums.length;
while (i < n) {
let correct = nums[i] - 1;
if (nums[i] !== nums[correct]) {
[nums[i], nums[correct]] = [nums[correct], 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(findErrorNums([1, 2, 2, 4])); // Output: [2, 3]
Line Notes
while (i < n)Iterate to place numbers at correct indices
let correct = nums[i] - 1;Calculate target index for current number
if (nums[i] !== nums[correct])Check if swap is needed
[nums[i], nums[correct]] = [nums[correct], nums[i]];Swap numbers to correct positions
Each number is swapped at most once to its correct position, so time is linear. No extra space is used besides variables.
💡 For n=100,000, this means about 100,000 operations, which is very efficient.
Interview Verdict: Accepted and optimal
This is the best approach for this problem, combining efficiency and clarity once understood.