Searching & Sorting · 34 of 36
Find the inversion count
Count how many pairs in a line are in the wrong order, with a bigger number standing before a smaller one.
- 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 numbers. A pair of positions i < j is out of order when arr[i] > arr[j]: a bigger number stands before a smaller one. Each such pair is an inversion.
Count them all. A sorted array has 0. An array sorted backwards has the most, n * (n - 1) / 2. The count tells you how far the array is from sorted.
A story to remember it
Picture it
Five out of order pairs in [5, 3, 8, 1, 6]: (5, 3), (5, 1), (3, 1), (8, 1) and (8, 6).
Examples
A normal case
- In
[5, 3, 8, 1, 6]- Out
5
The five pairs listed above. The walkthrough counts them with merge sort.
The classic one
- In
[2, 4, 1, 3, 5]- Out
3
(2, 1), (4, 1) and (4, 3).
Already sorted
- In
[1, 2, 3, 4, 5]- Out
0
Nobody stands before a smaller number.
Sorted backwards
- In
[5, 4, 3, 2, 1]- Out
10
Every pair is out of order: 5 * 4 / 2 = 10.
Equal numbers
- In
[2, 2, 1]- Out
2
Each 2 pairs with the 1. The two 2s are not out of order, because the rule says strictly bigger.
Way 1: the simple way
Check every pair. For each i, look at every later j and count when arr[i] > arr[j].
class Solution {
public long inversionCount(long[] arr) {
long count = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) count++; // bigger one stands first
}
}
return count;
}
}How long it takes: about n * n / 2 pair checks, O(n^2). With half a million numbers that is over a hundred billion checks. Extra room: O(1).
Way 2: the clever way
Every out of order pair is one of three kinds: both numbers in the left half, both in the right half, or one in each half. Merge sort already splits the array this way. So:
- Split in the middle. Count (and sort) the left half. Count (and sort) the right half. The smaller sorts do this by splitting again.
- Merge the two sorted halves with fingers
i(left) andj(right). - If
left[i] <= right[j], the left number goes down first. No new pairs. - If
right[j]is smaller, it goes down first, and every left number fromito the end of the left half is bigger and stood before it. Addmid - i + 1at once.
The tree shows the pieces. Each piece's note says how many pairs its merge found.
Count the pairs while merge sort merges
01 / 14
Cut the line in half again and again until every piece has one number. A single number has no out of order pairs.
- total
- 0
- looking now
- done
- answer
- rejected
- just added
class Solution {
public long inversionCount(long[] arr) {
if (arr.length < 2) return 0;
return sortAndCount(arr, new long[arr.length], 0, arr.length - 1);
}
private long sortAndCount(long[] a, long[] tmp, int lo, int hi) {
if (lo >= hi) return 0; // one number, no pairs
int mid = lo + (hi - lo) / 2;
long count = sortAndCount(a, tmp, lo, mid); // pairs inside the left half
count += sortAndCount(a, tmp, mid + 1, hi); // pairs inside the right half
int i = lo, j = mid + 1, k = lo;
while (i <= mid && j <= hi) {
if (a[i] <= a[j]) {
tmp[k++] = a[i++]; // left goes first, no new pairs
} else {
count += mid - i + 1; // every waiting left number is bigger
tmp[k++] = a[j++];
}
}
while (i <= mid) tmp[k++] = a[i++];
while (j <= hi) tmp[k++] = a[j++];
for (k = lo; k <= hi; k++) a[k] = tmp[k];
return count;
}
}How long it takes: the array is halved about log n times, and each level of merging touches every number once: O(n log n). Extra room: the helper array, O(n), plus O(log n) for waiting calls.
Watch out for
- The count can reach about
n^2 / 2, over a hundred billion for half a million numbers. Uselongfor the count. - The values themselves can be huge on GeeksforGeeks (up to
10^18), so store them inlong[]. - Add
mid - i + 1(all waiting left numbers), not 1. - The method sorts the input. Copy it first if the caller needs the original order.
What interviewers ask next
- Another
O(n log n)way? A Fenwick tree (binary indexed tree): walk from right to left, ask how many smaller numbers you have already seen, then add this one. Squash big values into ranks first. - What does the count mean? It equals the number of swaps bubble sort or insertion sort makes, and the fewest swaps of neighbours needed to sort the array.
- Count pairs with
arr[i] > 2 * arr[j](LeetCode 493, reverse pairs). Same merge sort, but count with a separate finger pass before the merge, since the count rule and the merge rule differ. - For each number, how many smaller numbers are on its right (LeetCode 315)? Same merge, but track original positions and add the count to each left number as it goes down.
- How similar are two rankings? Relabel one ranking by the other and count inversions. That is the Kendall tau distance.
Remember this
Grown-up words: an out of order pair is an inversion, splitting and merging is merge sort (divide and conquer), pairs across the two halves are split inversions, and the helper array is the auxiliary buffer.