Sorting · the fewest writes
Selection Sort,
one swap per pass.
Find the smallest value left, put it where it belongs, repeat. It is slow like bubble sort, but it writes to memory far less than bubble or insertion sort ever will — and that one strength costs you stability.
Run the selection simulation →01 The idea
Sort the way you sort cards on a table
Spread a hand of cards face up. You scan the whole spread, pick out the lowest card, and lay it down at the left end. Then you scan again, ignoring the cards you have already placed. Selection sort is exactly that, written down: a sorted region that grows from the left, and an unsorted region that shrinks.
02 Worked example
Selection sort on 5 1 4 2, by hand
Four numbers, three passes. Follow the 5: it starts at the front and gets pushed out of the way twice before it lands at the back. Each row below is the array after one full pass; green boxes are final, rose marks the value the swap displaced.
Count what that cost: 3 + 2 + 1 = 6 comparisons, and only 2 swaps. Slot 3 never got a pass of its own — once the other three slots were final, the largest value had nowhere else to be. That is the whole algorithm, and the code in the next section is these three passes written as two loops.
03 The code
Two loops, and the one line that saves the writes
Both versions below sort correctly and both make exactly the same 6 comparisons on 5 1 4 2. The only difference is how many times they write back into the array.
Naive · swap as you go
for i = 0 to n-2 for j = i+1 to n-1 if a[j] < a[i] swap a[i], a[j]
Selection sort · min index
for i = 0 to n-2 min = i for j = i+1 to n-1 if a[j] < a[min] min = j if min != i swap a[i], a[min]
Remember the position, not the value. min holds where the smallest sits, so nothing is written while you are still looking. Pass 2 of the trace found the 2 sitting at the far end; remembering its slot brought it home in one write, while the left version needed two.
One write per pass, not one per improvement. The left loop swaps every time it meets something smaller, so the running minimum is stored inside slot i and has to be rewritten each time it improves. On 5 1 4 2 that is 4 swaps against 2 — with identical comparison counts.
if min != i skips a pointless self-swap. Pass 3 found 4 already sitting in slot 2. Without the guard you read a value and write it straight back over itself: three assignments that change nothing.
The outer loop stops at n-2. A final pass over one element would compare it to nothing. By elimination it is already the largest, so the line is free to delete.
05 Cheat sheet
Everything you need the morning of the interview
| Case | Cost | Why |
|---|---|---|
| Best — already sorted | O(n²) | Every pass still scans the whole unsorted suffix. There is no early-exit signal to find. |
| Average — random order | O(n²) | Exactly n(n−1)/2 comparisons, always. For n = 4 that is 6. |
| Worst — reversed | O(n²) | Identical to the best case. Input order changes the swaps, never the comparisons. |
| Swaps — any input | O(n) | At most n−1, one per pass — and with the if min != i guard from section 03, fewer whenever a value is already in place. Far below bubble sort’s n(n−1)/2 or insertion sort’s shifting. |
| Extra space | O(1) | One index variable and one temporary for the swap. It rearranges the original array. |
06 Where & why
It is slow. Here is the one thing it is best at.
Selection sort is not the fastest sort and it is not the safest one to reach for. Its single real advantage is that it writes to memory fewer times than any of the sorts you are likely to reach for instead — bubble, insertion, merge, quick, heap — at most n−1 swaps, no matter how badly shuffled the input is.
Reach for it when…
Use something else when…
| Situation | Better choice | Why |
|---|---|---|
| The data is nearly sorted already | Insertion sort | It finishes in about O(n) on almost-sorted input. Selection sort still pays the full n(n−1)/2. |
| Equal keys must keep their original order | Insertion sort or merge sort | Both are stable. Selection sort’s long-distance swap can jump one equal value past another. |
| n is more than a few hundred | Your language’s built-in sort | Timsort and introsort run in O(n log n). At n = 1000 that is roughly 10,000 operations against 500,000. |
| You keep pulling the smallest from a changing set | A min-heap | Each extraction costs O(log n) instead of a fresh O(n) scan of everything left. |
07 Interview questions
What they actually ask about selection sort
Twelve questions in the order an interview escalates. Say each answer out loud — every one should land in about twenty seconds.
What is selection sort?
What is its time complexity?
Why is the best case still O(n²) when bubble sort’s is O(n)?
How many swaps does it perform?
How much extra memory does it need?
Is selection sort stable?
Is it adaptive?
Selection sort or bubble sort — which would you pick?
Selection sort or insertion sort?
Why does the outer loop stop at n-2 instead of n-1?
When would you actually use it in production?
How would you get the k smallest elements without sorting everything?
08 Practice problems
Six problems to write yourself
The first five are variations on the two loops from section 03. Save the hard one for last — it throws the loops away entirely and connects selection sort to permutation cycles.