🧠
Optimal Cyclic Sort In-Place
💡 This approach uses the problem's constraint that numbers are in [1, n] to place each number at its correct index. Duplicates are detected when a number is already at its correct position, enabling O(n) time and O(1) space.
Intuition
Place each number at the index equal to its value minus one. If a number is already at that index, it must be a duplicate.
Algorithm
- Initialize an empty list to store duplicates.
- Iterate over the array with index i.
- While the current element is not at its correct index and not equal to the element at its target index, swap it to its correct position.
- If a duplicate is detected (element equals the element at its correct index), move to next index.
- After placement, iterate through the array to collect elements not at their correct index as duplicates.
- Return the duplicates list.
💡 This algorithm rearranges elements in-place to detect duplicates without extra space, leveraging the input constraints.
def findDuplicates(nums):
duplicates = []
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:
duplicates.append(nums[i])
return duplicates
# Driver code
if __name__ == '__main__':
arr = [4,3,2,7,8,2,3,1]
print(findDuplicates(arr))
Line Notes
duplicates = []Prepare list to collect duplicates
while i < n:Traverse array to place elements correctly
correct_index = nums[i] - 1Calculate target index for current element
if nums[i] != nums[correct_index]:If current element not at correct place, swap it
import java.util.*;
public class Solution {
public static List<Integer> findDuplicates(int[] nums) {
List<Integer> duplicates = new ArrayList<>();
int i = 0;
int 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) {
duplicates.add(nums[i]);
}
}
return duplicates;
}
public static void main(String[] args) {
int[] arr = {4,3,2,7,8,2,3,1};
System.out.println(findDuplicates(arr));
}
}
Line Notes
List<Integer> duplicates = new ArrayList<>();List to store duplicates found
while (i < n) {Traverse array to place elements at correct indices
int correctIndex = nums[i] - 1;Calculate correct index for current element
if (nums[i] != nums[correctIndex]) {Swap if element not at correct position
#include <iostream>
#include <vector>
using namespace std;
vector<int> findDuplicates(vector<int>& nums) {
vector<int> duplicates;
int i = 0;
int 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) {
duplicates.push_back(nums[i]);
}
}
return duplicates;
}
int main() {
vector<int> arr = {4,3,2,7,8,2,3,1};
vector<int> res = findDuplicates(arr);
for (int x : res) cout << x << " ";
cout << endl;
return 0;
}
Line Notes
vector<int> duplicates;Stores duplicates found
while (i < n) {Loop to place elements at correct indices
int correctIndex = nums[i] - 1;Calculate target index for current element
if (nums[i] != nums[correctIndex]) {Swap elements to correct positions
function findDuplicates(nums) {
const duplicates = [];
let i = 0;
const n = nums.length;
while (i < n) {
const 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) duplicates.push(nums[i]);
}
return duplicates;
}
// Test
const arr = [4,3,2,7,8,2,3,1];
console.log(findDuplicates(arr));
Line Notes
const duplicates = []Initialize array to hold duplicates
while (i < n) {Loop to place elements at correct indices
const correctIndex = nums[i] - 1;Calculate correct index for current element
if (nums[i] !== nums[correctIndex]) {Swap elements if not in correct position
Each element is swapped at most once to its correct position, so linear time. No extra space except output list.
💡 For n=20, about 20 swaps or less, very efficient compared to previous methods.
Interview Verdict: Accepted and optimal
This is the best approach for this problem, demonstrating mastery of cyclic sort and in-place algorithms.