Count number of Inversions in an array

tutorials

Given an array of integers, the task is to count the number of inversions in the array.
In an array, an inversion is a pair of elements (arr[i], arr[j]) such that i < j and arr[i] > arr[j]

Input/Output Examples:

plaintext
Example 1:
Input:
arr = [8, 4, 2, 1]
Output: 6
Explanation: There are 6 inversions in the array: (8, 4), (8, 2), (8, 1), (4, 2), (4, 1), and (2, 1).

Example 2:
Input:
arr = [3, 1, 2]
Output: 2
Explanation: There are 2 inversions in the array: (3, 1) and (3, 2).

Example 3:
Input:
arr = [1, 2, 3, 4]
Output: 0
Explanation: The array is already sorted, so there are no inversions.

Approach to count the number of inversions in an array

  1. Use a Modified Merge Sort:
    • Inversions can be counted efficiently using a modified merge sort algorithm. During the merge step, count the number of inversions for each split pair.
  2. Count Inversions During Merge:
    • While merging two halves, if left[i] > right[j], then all remaining elements in the left half (from i onward) are greater than right[j], and this counts as inversions.
  3. Recursively Sort and Count:
    • Recursively sort the array while counting the inversions. Each merge operation contributes to the overall count of inversions.

C++ Program to count the number of inversions in an array

cpp
#include <iostream>
#include <vector>
using namespace std;

// Function to merge two halves and count inversions
int mergeAndCount(vector<int>& arr, vector<int>& temp, int left, int mid, int right) {
    int i = left;    // Starting index for left subarray
    int j = mid + 1; // Starting index for right subarray
    int k = left;    // Starting index to be sorted
    int inversions = 0;

    while (i <= mid && j <= right) {
        if (arr[i] <= arr[j]) {
            temp[k++] = arr[i++];
        } else {
            temp[k++] = arr[j++];
            inversions += (mid - i + 1);
        }
    }

    while (i <= mid)
        temp[k++] = arr[i++];

    while (j <= right)
        temp[k++] = arr[j++];

    for (i = left; i <= right; i++)
        arr[i] = temp[i];

    return inversions;
}

// Function to recursively sort and count inversions
int mergeSortAndCount(vector<int>& arr, vector<int>& temp, int left, int right) {
    int inversions = 0;
    if (left < right) {
        int mid = (left + right) / 2;

        inversions += mergeSortAndCount(arr, temp, left, mid);
        inversions += mergeSortAndCount(arr, temp, mid + 1, right);
        inversions += mergeAndCount(arr, temp, left, mid, right);
    }
    return inversions;
}

// Function to count inversions in the array
int countInversions(vector<int>& arr) {
    vector<int> temp(arr.size());
    return mergeSortAndCount(arr, temp, 0, arr.size() - 1);
}

int main() {
    vector<int> arr = {8, 4, 2, 1};
    cout << "Number of inversions: " << countInversions(arr) << endl;
    return 0;
}

Java Program to count the number of inversions in an array

java
public class InversionCount {

    // Function to merge two halves and count inversions
    private static int mergeAndCount(int[] arr, int[] temp, int left, int mid, int right) {
        int i = left;    // Starting index for left subarray
        int j = mid + 1; // Starting index for right subarray
        int k = left;    // Starting index to be sorted
        int inversions = 0;

        while (i <= mid && j <= right) {
            if (arr[i] <= arr[j]) {
                temp[k++] = arr[i++];
            } else {
                temp[k++] = arr[j++];
                inversions += (mid - i + 1);
            }
        }

        while (i <= mid)
            temp[k++] = arr[i++];

        while (j <= right)
            temp[k++] = arr[j++];

        for (i = left; i <= right; i++)
            arr[i] = temp[i];

        return inversions;
    }

    // Function to recursively sort and count inversions
    private static int mergeSortAndCount(int[] arr, int[] temp, int left, int right) {
        int inversions = 0;
        if (left < right) {
            int mid = (left + right) / 2;

            inversions += mergeSortAndCount(arr, temp, left, mid);
            inversions += mergeSortAndCount(arr, temp, mid + 1, right);
            inversions += mergeAndCount(arr, temp, left, mid, right);
        }
        return inversions;
    }

    // Function to count inversions in the array
    public static int countInversions(int[] arr) {
        int[] temp = new int[arr.length];
        return mergeSortAndCount(arr, temp, 0, arr.length - 1);
    }

    public static void main(String[] args) {
        int[] arr = {8, 4, 2, 1};
        System.out.println("Number of inversions: " + countInversions(arr));
    }
}

Python Program to count the number of inversions in an array

python
# Function to merge two halves and count inversions
def merge_and_count(arr, temp, left, mid, right):
    i = left    # Starting index for left subarray
    j = mid + 1 # Starting index for right subarray
    k = left    # Starting index to be sorted
    inversions = 0

    while i <= mid and j <= right:
        if arr[i] <= arr[j]:
            temp[k] = arr[i]
            i += 1
        else:
            temp[k] = arr[j]
            inversions += (mid - i + 1)
            j += 1
        k += 1

    while i <= mid:
        temp[k] = arr[i]
        i += 1
        k += 1

    while j <= right:
        temp[k] = arr[j]
        j += 1
        k += 1

    for i in range(left, right + 1):
        arr[i] = temp[i]

    return inversions

# Function to recursively sort and count inversions
def merge_sort_and_count(arr, temp, left, right):
    inversions = 0
    if left < right:
        mid = (left + right) // 2

        inversions += merge_sort_and_count(arr, temp, left, mid)
        inversions += merge_sort_and_count(arr, temp, mid + 1, right)
        inversions += merge_and_count(arr, temp, left, mid, right)

    return inversions

# Function to count inversions in the array
def count_inversions(arr):
    temp = [0] * len(arr)
    return merge_sort_and_count(arr, temp, 0, len(arr) - 1)

# Example usage
if __name__ == "__main__":
    arr = [8, 4, 2, 1]
    print("Number of inversions:", count_inversions(arr))

Time Complexity

  • O(n log n): The modified merge sort algorithm has a time complexity of O(n log n) due to the recursive splitting and merging steps.

Space Complexity

  • O(n): Additional space is needed for the temporary array used during merging.
tools

DSA

Related Articles