When the values are a known range 1..n, each has one home (value v at index v−1). Swap each value home in place — no comparisons, O(n).
Cyclic sort works only when the values are a known range like 1 to n, where every value has exactly one correct home: value `v` belongs at index `v − 1`. It walks the array and, whenever a value is in the wrong spot, swaps it straight home. Because each swap puts at least one value where it belongs, the whole array sorts in a single sweep — with no comparisons.
i and look at the value there, v.v − 1. If v is already home (i === v − 1), move on: i++.v to its home index, bringing whatever lived there back to i.i after a swap — re-examine the new value now sitting at i.i reaches the end.[5, 1, 3, 4, 2]. Don't advance.[2, 1, 3, 4, 5]. Don't advance.[1, 2, 3, 4, 5]. Don't advance.[1, 2, 3, 4, 5].i whose value isn't i + 1 exposes an anomaly — that's how cyclic sort finds a missing number or duplicate in O(n). Add a guard so equal values don't swap forever: only swap when the target slot doesn't already hold the same value.// Array holds values in 1..n, one number missing (and one duplicated).
// Sort in place, then the first mismatch reveals both.
function findMissing(nums) {
let i = 0;
while (i < nums.length) {
const home = nums[i] - 1; // value v belongs at index v-1
if (nums[i] !== nums[home]) { // guard against equal-value loops
[nums[i], nums[home]] = [nums[home], nums[i]]; // swap home
} else {
i++; // in place (or a duplicate) -> move on
}
}
for (let k = 0; k < nums.length; k++) {
if (nums[k] !== k + 1) return k + 1; // this value never arrived
}
return nums.length + 1;
}
// findMissing([1, 2, 4, 4, 5]) -> 3 (index 2 holds 4, not 3)