The values are in 1..n and the array has length n, so the array is almost
a permutation of its own index set — and that is a data structure, not a coincidence. Value
v has exactly one correct home: index v−1. Pass one
walks i and repeatedly swaps whatever is sitting at i into its home
slot until nothing more can move. Pass two just reads off every index that ended up not holding
index+1; those are the missing numbers. This page shows the swap form because it is
the one that generalises — the same loop, plus a range check, solves LeetCode 41. The other
accepted answer is negative marking: walk the array and flip
nums[abs(v)-1] negative to record "v was seen", then report every still-positive
index. It is shorter and never moves an element, but it only works because these values are guaranteed
positive and in range, and it destroys the sign bit. Cyclic sort survives negatives, zeros and huge
values; negative marking does not.
n swaps happen across
the entire outer loop. The guard is nums[i] != nums[nums[i]-1] — compare
values, not indices, or duplicates spin forever.