Count Inversions
Count Inversions is a GFG problem (Medium). Given an integer array arr, return its inversion count: the number of pairs (i, j) with i < j and arr[i] > arr[j].
- The count measures how far the array is from sorted: 0 when sorted, n(n−1)/2 when reversed.
- Equal values do not form an inversion.
- With up to 10⁵ elements, checking every pair is too slow; the expected time is O(n log n).
- 1 ≤ arr.size() ≤ 10⁵
- 1 ≤ arr[i] ≤ 10⁴
Intuition
Split the array into a left half and a right half. Every inversion is one of three kinds:
- Both values in the left half, or both in the right half: the same problem on a smaller array, so recursion counts them.
- One value in each half: counted while the two halves are merged.
The cross pairs are cheap to count once both halves are sorted. If a right value is smaller than the left value arr[i], it is also smaller than every left value after arr[i], and all of them come before it in the array. So it adds mid - i inversions in one step. That is the count inversions merge sort idea.
"Count pairs i < j where the earlier value is larger" (or any order-based pair count) points to merge sort with a counter: each merge sees exactly the pairs that cross its two halves. The same idea solves Reverse Pairs (LeetCode 493, count before merging) and Count of Smaller Numbers After Self (LeetCode 315).
Approach
Before reading on: merge [2, 4] with [1, 3, 5]. When 1 is taken from the right, how many values in the left half is it smaller than? Do you need to compare it with each of them?
Two ways to solve it
Sort both halves recursively; while merging, a right value placed first adds every left value still waiting.
- Speed: fast enough for 10⁵ values.
- Memory: an O(n) merge buffer.
- Side effect: sorts
arr.
The expected answer on GFG.
Two nested loops compare each arr[i] with every later arr[j] and count the larger-first pairs.
- Speed: about 5 · 10⁹ checks at n = 10⁵.
- Memory: none extra.
- Code: five lines.
Only for small inputs or to test the fast one.
Merge sort counts whole groups of pairs at once instead of one pair at a time, so the steps, code and live demo below follow it. The pair-checking code comes after the demo.
Split and count each half
sort(lo, hi) returns the inversions inside arr[lo:hi] and leaves that range sorted. A range of one element has none. Otherwise it calls itself on both halves and adds their counts, so only pairs that cross the middle are left.
Merge with two pointers
i walks the left half and j the right one; each step moves the smaller value into merged.
arr[i] <= arr[j]: takearr[i]. No inversion, and ties count as none.arr[j] < arr[i]: takearr[j]and addmid - i, one for each left value still waiting, since all of them are at leastarr[i].
Copy the rest and write back
When one half runs out, append what is left of the other; those values form no new inversions. Then write merged into arr[lo:hi]. The range must end up sorted, because the parent merge relies on that to count in batches.
Return the total
sort(0, n) returns the inversion count. Each pair is counted once, in the merge where its two values first fall into different halves. There are log n levels of O(n) merging, so the time is O(n log n).
Count Inversions solution in Python | C++ | Java
sort(0, n) splits the array in half again and again. A piece of one element is sorted and holds no inversions, so the real work happens on the way back up, when two sorted halves are merged.arr. This piece is now sorted, which is exactly what the next merge up needs: the batch count mid − i is only correct when the left half is sorted.arr. This piece is now sorted, which is exactly what the next merge up needs: the batch count mid − i is only correct when the left half is sorted.arr. This piece is now sorted, which is exactly what the next merge up needs: the batch count mid − i is only correct when the left half is sorted.mid − i = 2 counts them in one step instead of one by one.mid − i = 1 counts them in one step instead of one by one.arr. This piece is now sorted, which is exactly what the next merge up needs: the batch count mid − i is only correct when the left half is sorted.sort(0, n) splits the array in half again and again. A piece of one element is sorted and holds no inversions, so the real work happens on the way back up, when two sorted halves are merged.mid − i = 1 counts them in one step instead of one by one.arr. This piece is now sorted, which is exactly what the next merge up needs: the batch count mid − i is only correct when the left half is sorted.mid − i = 1 counts them in one step instead of one by one.arr. This piece is now sorted, which is exactly what the next merge up needs: the batch count mid − i is only correct when the left half is sorted.mid − i = 1 counts them in one step instead of one by one.mid − i = 1 counts them in one step instead of one by one.arr. This piece is now sorted, which is exactly what the next merge up needs: the batch count mid − i is only correct when the left half is sorted.mid − i = 2 counts them in one step instead of one by one.mid − i = 2 counts them in one step instead of one by one.mid − i = 2 counts them in one step instead of one by one.arr. This piece is now sorted, which is exactly what the next merge up needs: the batch count mid − i is only correct when the left half is sorted.sort(0, n) splits the array in half again and again. A piece of one element is sorted and holds no inversions, so the real work happens on the way back up, when two sorted halves are merged.<=.arr. This piece is now sorted, which is exactly what the next merge up needs: the batch count mid − i is only correct when the left half is sorted.<=.arr. This piece is now sorted, which is exactly what the next merge up needs: the batch count mid − i is only correct when the left half is sorted.Brute force (every pair)
For each index i, look at every later index j and count the pairs where arr[i] > arr[j].
Common pitfalls
Adding 1 instead of mid - i
else:
inv += 1else:
inv += mid - iThe right value is smaller than every left value still waiting, not just arr[i]. On [2, 4, 1, 3, 5] adding 1 per step returns 2 instead of 3.
Using < so ties go to the counting branch
if arr[i] < arr[j]:
if arr[i] <= arr[j]:
Equal values are not an inversion. With <, [10, 10, 10] reports 1 instead of 0.
Forgetting the counts from the halves
inv = 0
inv = sort(lo, mid) + sort(mid, hi)
The merge only sees pairs that cross the middle. Pairs inside each half were counted by the recursive calls, and dropping them gives only the top-level cross pairs.
Edge cases
Every pair is inverted, n(n − 1) / 2 in total. For n = 10⁵ that is about 5 × 10⁹, past a 32-bit int, so keep the count in a long / long long.
Complexity
Count Inversions FAQ
Does counting inversions with merge sort change the array?
Yes, arr ends up sorted. If the caller still needs the original order, run the count on a copy (arr[:] in Python, arr.clone() in Java).
Can a Fenwick tree count inversions in an array?
Yes. Scan from right to left, and for each value ask the Fenwick tree how many smaller values were already seen, then add the value. With values up to 10⁴ that is also O(n log n), but merge sort needs no extra structure.