Let's look at what cyclic sort with the duplicate guard leaves behind.
Start with [1, 3, 2, 3, 5] and run the full algorithm. You get:
const sorted = [1, 2, 3, 3, 5];// index: 0 1 2 3 4// expected: 1 2 3 4 5Almost sorted. Index 0 holds 1 — correct. Index 1 holds 2 — correct.
Index 2 holds 3 — correct. Index 4 holds 5 — correct. But index 3
holds 3 instead of 4. That's the imposter — the duplicate that couldn't
be placed because its home was already occupied.
One position is wrong. But that single mismatch is hiding two pieces of
information. What should be at index 3? The value 4 — that's the missing
number. What is at index 3? The value 3 — that's the duplicate. The same
mismatch tells you both who's absent and who showed up twice. Think of it like
a seating chart at a dinner party: if seat 4 has the wrong guest, you instantly
know which guest is missing (the one assigned to seat 4) and which guest is a
gatecrasher (whoever is actually sitting there).
This duality is the engine behind an entire family of LeetCode problems. Let's see it in action.
After cyclic sort, every value should equal its index + 1. Without checking each cell, what KIND of position would break this rule?
After cyclic sort, one linear scan extracts everything you need:
for (let i = 0; i < n; i++) { if (nums[i] !== i + 1) { const missing = i + 1; // what SHOULD be here const duplicate = nums[i]; // what IS here (the imposter) }}That's the whole pattern. The scan walks each index and asks one question: does
this position hold its rightful owner? If yes, move on. If no, you've found a
mismatch — and every mismatch has two faces. The expected value (i + 1) is
missing from the array. The actual value (nums[i]) appears more times than
it should.
Now watch how this single scan maps to four different LeetCode problems. LC 268
(Missing Number) asks “which value is absent?” — you return missing. LC 287
(Find the Duplicate Number) asks “which value appears twice?” — you return
duplicate. LC 442 (Find All Duplicates) asks for every duplicate — you
collect all duplicate values. LC 448 (Find All Numbers Disappeared) asks for
every missing value — you collect all missing values. Same cyclic sort. Same
scan. Same two-faced mismatch. The only thing that changes is which face you
read and whether you collect one result or many.
Every undeliverable letter in the mailroom tells you both who's missing from the route and who sent a copy. You just need to know which question the problem is asking. Next: what happens when the mailbag includes junk?