Count Inversions in an array

Merge sort approach

Problem

Given an array of N integers, count the inversion of the array

What is an inversion of an array? Definition: for all i & j < size of array, if i < j then you have to find pair (A[i], A[j]) such that A[j] < A[i].

link

Brute Force Approach

Find all pairs and count those in which the first element is greater than the second. This can be achieved using two nested for-loops

public class Solution {
    public static int numberOfInversions(int []a, int n) {
        int pairs = 0;
        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                if(a[i]>a[j]) pairs+=1;
            }
        }
        return pairs;
    }
}

Optimal Approach (Merge Sort)

We will use merge sort. The root idea is that if we have two sorted arrays, then we can easily find the count of inversions. If arr1[i] > arr2[j], then all elements in arr1 (i, i+1, ...) will form good pairs with arr2[j]

Code

public class Solution {
    public static int numberOfInversions(int []a, int n) {
       return mergeInversions(a, 0, n-1);
    }
    private static int mergeInversions(int[] a, int low, int high) {
        if (low==high) return 0;
        int mid = (low+high)/2;
        int leftInversionCount = mergeInversions(a, low,mid);
        int rightInversionCount = mergeInversions(a, mid+1, high);
        return leftInversionCount+rightInversionCount+mergeInversionCount(a, low, mid, high);
    }

    private static int mergeInversionCount(int[] arr, int low, int mid, int high) {
        int inversionCount = 0;
        int ptr1 = low;
        int ptr2 = mid+1;
        int n = high-low+1;
        int dummy[] = new int[n];

        int index = 0;
        while (ptr1<=mid && ptr2<=high){
            if (arr[ptr1]<=arr[ptr2]){
                dummy[index] = arr[ptr1];
                index+=1;
                ptr1+=1;
            }else {
                dummy[index] = arr[ptr2];
                index+=1;
                ptr2+=1;
                inversionCount+=(mid-ptr1+1);
            }
        }

        while (ptr1<=mid){
            dummy[index] = arr[ptr1];
            ptr1+=1;
            index+=1;
        }

        while (ptr2<=high){
            dummy[index] = arr[ptr2];
            ptr2+=1;
            index+=1;
        }

        for (int i=0; i<n; i++){
            arr[low+i] = dummy[i];
        }

        return inversionCount;
    }
}