Count Inversions
Problem Statement
Given an array arr[], count the number of inversions in the array. Two elements arr[i] and arr[j] form an inversion if i < j and arr[i] > arr[j].
Example: Input: arr = [8, 4, 2, 1]
Output: 6
Explanation: Inversions are (8,4), (8,2), (8,1), (4,2), (4,1), (2,1).
Approach 1: Brute Force
Explanation: Use two nested loops to check every pair of elements and count inversions where i < j and arr[i] > arr[j].
Time Complexity: O(n2)
Space Complexity: O(1)
function countInversions(arr): n = length(arr) count = 0 for i = 0 to n-2: for j = i+1 to n-1: if arr[i] > arr[j]: count = count + 1 return count
Approach 2: Optimized Brute Force with Early Termination
Explanation: Similar to brute force but with minor optimizations like reducing redundant comparisons. Though still O(n²), it performs better in practice by avoiding unnecessary iterations when possible.
Time Complexity: O(n2)
Space Complexity: O(1)
function countInversions(arr): n = length(arr) count = 0 for i = 0 to n-2: // Early termination: if current element is smallest, // no inversions possible if arr[i] <= min(arr[i+1] to arr[n-1]): continue for j = i+1 to n-1: if arr[i] > arr[j]: count = count + 1 return count
Approach 3: Divide and Conquer (Modified Merge Sort)
Explanation: Divide the array into two halves. Count inversions in left half, right half, and cross inversions during merge. When merging, if an element from the right half is smaller than an element from the left half, all remaining elements in the left half form inversions with it.
Time Complexity: O(n log n)
Space Complexity: O(n) for temporary array
function mergeAndCount(arr, temp, left, mid, right): i = left j = mid + 1 k = left invCount = 0 while i <= mid and j <= right: if arr[i] <= arr[j]: temp[k] = arr[i] i = i + 1 else: temp[k] = arr[j] invCount = invCount + (mid - i + 1) j = j + 1 k = k + 1 while i <= mid: temp[k] = arr[i] i = i + 1 k = k + 1 while j <= right: temp[k] = arr[j] j = j + 1 k = k + 1 for i = left to right: arr[i] = temp[i] return invCount function mergeSortAndCount(arr, temp, left, right): invCount = 0 if left < right: mid = (left + right) / 2 invCount = invCount + mergeSortAndCount(arr, temp, left, mid) invCount = invCount + mergeSortAndCount(arr, temp, mid+1, right) invCount = invCount + mergeAndCount(arr, temp, left, mid, right) return invCount function countInversions(arr): n = length(arr) temp = new array of size n return mergeSortAndCount(arr, temp, 0, n-1)
The Divide and Conquer approach using Modified Merge Sort is the most commonly used optimal solution for counting inversions with O(n log n) time complexity. It elegantly combines sorting with inversion counting.
