Skip to content
dsa450for five year olds

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

array
0123424135
setout of order pairs
(2, 1)(4, 1)(4, 3)

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].

array
0123424135ji

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
java
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.

  1. Split the array in the middle. Count and sort the left half. Count and sort the right half.
  2. Merge the two sorted halves with fingers i (left) and j (right).
  3. If left[i] <= right[j], the left number goes down first. No new pairs.
  4. If right[j] is smaller, it goes down first. Every left number from i to 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

treesplit and merge
2 4 1 3 52 4 12 42413 535

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
java
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. Use long.
  • 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.