Searching & Sorting · 18 of 36
Minimum no. of swaps required to sort the array
Kids sit in the wrong chairs. Count the fewest swaps to seat everyone right by finding the circles of kids who are sitting in one another's chairs.
- Simple way
- time O(n^2)
room O(1) - Clever way
- time O(n log n)
room O(n)
The problem, simply
You get an array of different numbers. In one swap you may pick any two positions and swap their numbers. They do not have to be next to each other. Give back the smallest number of swaps that makes the array sorted.
You only return the count, not the swaps themselves.
A story to remember it
Picture it
The array [2, 4, 5, 1, 3]. Each arrow goes from a number to the number now sitting in its correct seat. Two circles: 2, 4, 1 (3 numbers) and 5, 3 (2 numbers). Swaps = (3 - 1) + (2 - 1) = 3.
Examples
A normal case
- In
[2, 4, 5, 1, 3]- Out
3
One circle of 3 needs 2 swaps, one circle of 2 needs 1 swap.
Fully reversed
- In
[4, 3, 2, 1]- Out
2
Two circles of 2: swap 4 with 1, then 3 with 2.
Some already home
- In
[10, 19, 6, 3, 5]- Out
2
Sorted is [3, 5, 6, 10, 19]. 6 is already home. 10 and 3 swap, 19 and 5 swap.
Already sorted
- In
[1, 2, 3]- Out
0
Every number is a circle of 1. No swaps.
Way 1: the simple way
Do selection sort and count its swaps. For each seat from left to right, find the smallest number in the rest of the row. If it is not already in this seat, swap it in and count one.
- For
ifrom 0 ton - 2, find the indexminIdxof the smallest number inarr[i..n-1]. - If
minIdx != i, swap and add 1 to the count.
Each swap sends one number to its final seat, and the very last swap of a circle sends two numbers home. So this count is the true minimum. It is only slow.
class Solution {
public int minSwaps(int[] arr) {
int[] a = arr.clone();
int n = a.length, swaps = 0;
for (int i = 0; i < n - 1; i++) {
int minIdx = i;
for (int j = i + 1; j < n; j++) {
if (a[j] < a[minIdx]) minIdx = j; // smallest in the rest
}
if (minIdx != i) { // not home yet: swap it in
int t = a[i]; a[i] = a[minIdx]; a[minIdx] = t;
swaps++;
}
}
return swaps;
}
}How long it takes: for each seat we scan the rest of the row, O(n^2). Extra room: a copy so we do not wreck the input, or O(1) if you may change it.
Way 2: the clever way
Find the circles without doing any swaps.
- Sort the positions by their numbers. That tells you
target[i]: the seat where the number at positionibelongs. - Keep a
seenmark for each position. - For each position
inot seen yet, follow the arrowsj = target[j]until you come back, marking each one seen and counting the circle's sizek. - Add
k - 1to the answer.
The answer is also n minus the number of circles.
Follow the arrows, count the circles
01 / 09
Sort tells us each number's seat: 1 goes to seat 0, 2 to seat 1, and so on. So target = [1, 3, 4, 0, 2]: the 2 at position 0 belongs in seat 1.
- swaps
- 0
- looking now
- done
- answer
- path
class Solution {
public int minSwaps(int[] arr) {
int n = arr.length;
Integer[] order = new Integer[n]; // positions, sorted by their number
for (int i = 0; i < n; i++) order[i] = i;
Arrays.sort(order, (x, y) -> Integer.compare(arr[x], arr[y]));
int[] target = new int[n]; // target[i] = seat where arr[i] belongs
for (int k = 0; k < n; k++) target[order[k]] = k;
boolean[] seen = new boolean[n];
int swaps = 0;
for (int i = 0; i < n; i++) {
if (seen[i] || target[i] == i) continue; // done, or already home
int size = 0;
for (int j = i; !seen[j]; j = target[j]) { // walk around the circle
seen[j] = true;
size++;
}
swaps += size - 1; // a circle of size k needs k - 1 swaps
}
return swaps;
}
}How long it takes: sorting is O(n log n), and the circle walk touches each position once, O(n). Extra room: target, order and seen, O(n).
Watch out for
- Selection sort does give the minimum here, so do not call it wrong. It is correct but
O(n^2). Bubble sort's swap count is the neighbor-swap answer, which is bigger. - Duplicates break the "each number has one home" idea. With repeats, a number can choose among several seats and you need extra care (for example, stable sort by value then index).
- Comparing with
a - bin a comparator can overflow for huge numbers. UseInteger.compare. - Forgetting to skip positions that are already seen makes you count a circle twice.
What interviewers ask next
- Return the actual swaps. Walk each circle: keep swapping the number at
iinto its target seat until seatiholds its own number. - Minimum swaps to make two arrays equal, or to turn one permutation into another. Map the second array's positions, then count circles the same way.
- Minimum swaps to sort a binary tree level by level. Do the circle count on each level's values.
- Why is
k - 1the best for a circle ofk? One swap can at most split one circle into two, and you needkcircles of size 1 at the end, so you need at leastk - 1swaps.
Remember this
Grown-up words: the seating plan is a permutation, the circles of kids are cycles in a directed graph, n - cycles is the cycle decomposition formula, and the neighbor-only version counts inversions.