Array · 25 of 36
Count Inversion
Count how many pairs in a line are in the wrong order, where a bigger number stands 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 if arr[i] > arr[j]: the bigger number stands before the smaller one. Such a pair is called an inversion.
Count all of them. A sorted array has 0. An array sorted backwards has the most.
A story to remember it
Picture it
Three pairs are out of order: 2 stands before 1, 4 stands before 1, and 4 stands before 3.
- checking
- rejected
Examples
A normal case
- In
[2, 4, 1, 3, 5]- Out
3
The pairs (2, 1), (4, 1) and (4, 3).
Already sorted
- In
[1, 2, 3, 4, 5]- Out
0
No bigger number ever stands before a smaller one.
Sorted backwards
- In
[5, 4, 3, 2, 1]- Out
10
Every pair is out of order. With n numbers that is n * (n - 1) / 2 = 5 * 4 / 2 = 10, the most possible.
Equal numbers
- In
[2, 2, 1]- Out
2
Each 2 makes a pair with the 1. The two 2s do not count, because the rule needs strictly bigger.
Way 1: the simple way
Look at every pair. For each position i, check every later position j and count the pairs where arr[i] > arr[j].
With i on 4, j walks over every later number. 4 is bigger than 1 and than 3, so i = 1 adds two pairs.
- looking now
- checking
- rejected
class Solution {
public long countInversions(int[] 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: every pair once, about n * n / 2 checks, O(n^2). Extra room: one counter, O(1).
Way 2: the clever way
Use merge sort and count while merging. 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. The first two kinds are counted by the smaller sorts. The third kind is counted during the merge.
- Split the array in the middle. Count and sort the left half. Count and sort the right half.
- 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. Every left number fromito the end of the left half is bigger and stood before it. Add that many,mid - i + 1, in one go.
Count the pairs while merge sort merges
01 / 11
Cut the line in half again and again until every piece has one number. One number alone has no pairs, so it has 0 inversions.
- total
- 0
- looking now
- done
- answer
- rejected
- just added
class Solution {
public long countInversions(int[] arr) {
if (arr.length < 2) return 0;
return sortAndCount(arr, new int[arr.length], 0, arr.length - 1);
}
private long sortAndCount(int[] a, int[] tmp, int lo, int hi) {
if (lo >= hi) return 0; // one number has 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; // all waiting left numbers are 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 cut in half about log n times, and each level of merging touches every number once, so O(n log n). Extra room: the helper array tmp, O(n), plus O(log n) for the waiting calls.
Watch out for
- The count can be huge. With 100,000 numbers sorted backwards it is about 5 billion, which does not fit in an
int. Uselong. - The method sorts the array. Pass a copy if the caller needs the original order.
- Add
mid - i + 1, the count of left numbers still waiting, not 1.
What interviewers ask next
- Can you do it another way in
O(n log n)? Yes, with a Fenwick tree (a binary indexed tree). Walk from right to left, and for each number ask how many smaller numbers you have already seen, then record this one. Squash big values to ranks first. - What does the count mean? It is the number of swaps bubble sort makes, and the fewest swaps of neighbours needed to sort the array.
- Count pairs where
arr[i] > 2 * arr[j](reverse pairs). Same merge sort shape, but count with a separate pointer pass before merging, because the merge condition and the count condition differ. - How similar are two rankings? Relabel one ranking by the other and count inversions. This is the Kendall tau distance.
Remember this
Grown-up words: the messy pairs are inversions, splitting and merging is merge sort (divide and conquer), the pairs with one number in each half are split inversions, and the counting tree from the follow up is a Fenwick tree.