Count Inversions of an Array
Last Updated :
01 Dec, 2024
Given an integer array arr[] of size n, find the inversion count in the array. Two array elements arr[i] and arr[j] form an inversion if arr[i] > arr[j] and i < j.
Note: Inversion Count for an array indicates that how far (or close) the array is from being sorted. If the array is already sorted, then the inversion count is 0, but if the array is sorted in reverse order, the inversion count is maximum.
Examples:
Input: arr[] = {4, 3, 2, 1}
Output: 6
Explanation:
Input: arr[] = {1, 2, 3, 4, 5}
Output: 0
Explanation: There is no pair of indexes (i, j) exists in the given array such that arr[i] > arr[j] and i < j
Input: arr[] = {10, 10, 10}
Output: 0
[Naive Approach] Using Two Nested Loops - O(n^2) Time and O(1) Space
Traverse through the array, and for every index, find the number of smaller elements on its right side in the array. This can be done using a nested loop. Sum up the inversion counts for all indices in the array and return the sum.
C++
// C++ program to Count Inversions in an array
// using nested loop
#include <iostream>
#include <vector>
using namespace std;
// Function to count inversions in the array
int inversionCount(vector<int> &arr) {
int n = arr.size();
int invCount = 0;
// Loop through the array
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
// If the current element is greater
// than the next, increment the count
if (arr[i] > arr[j])
invCount++;
}
}
return invCount;
}
int main() {
vector<int> arr = {4, 3, 2, 1};
cout << inversionCount(arr) << endl;
return 0;
}
C
// C program to Count Inversions in an array
// using nested loop
#include <stdio.h>
// Function to count inversions in the array
int inversionCount(int arr[], int n) {
int invCount = 0;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
// If the current element is greater than the next,
// increment the count
if (arr[i] > arr[j])
invCount++;
}
}
return invCount;
}
int main() {
int arr[] = {4, 3, 2, 1};
int n = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", inversionCount(arr, n));
return 0;
}
Java
// Java program to Count Inversions in an array
// using nested loop
import java.util.*;
class GfG {
// Function to count inversions in the array
static int inversionCount(int arr[]) {
int n = arr.length;
int invCount = 0;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
// If the current element is greater than the next,
// increment the count
if (arr[i] > arr[j])
invCount++;
}
}
return invCount;
}
public static void main(String[] args) {
int arr[] = {4, 3, 2, 1};
System.out.println(inversionCount(arr));
}
}
Python
# Python program to Count Inversions in an array
# using nested loop
# Function to count inversions in the array
def inversionCount(arr):
n = len(arr)
invCount = 0
for i in range(n - 1):
for j in range(i + 1, n):
# If the current element is greater than the next,
# increment the count
if arr[i] > arr[j]:
invCount += 1
return invCount
if __name__ == "__main__":
arr = [4, 3, 2, 1]
print(inversionCount(arr))
C#
// C# program to Count Inversions in an array
// using nested loop
using System;
class GfG {
// Function to count inversions in the array
static int inversionCount(int[] arr) {
int n = arr.Length;
int invCount = 0;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
// If the current element is greater than the next,
// increment the count
if (arr[i] > arr[j])
invCount++;
}
}
return invCount;
}
static void Main() {
int[] arr = { 4, 3, 2, 1 };
Console.WriteLine(inversionCount(arr));
}
}
JavaScript
// JavaScript program to Count Inversions in an array
// using nested loop
function inversionCount(arr) {
let n = arr.length;
let invCount = 0;
// Loop through the array
for (let i = 0; i < n - 1; i++) {
for (let j = i + 1; j < n; j++) {
// If the current element is greater than the next,
// increment the count
if (arr[i] > arr[j]) {
invCount++;
}
}
}
return invCount;
}
// driver code
let arr = [4, 3, 2, 1];
console.log(inversionCount(arr));
[Expected Approach] Using Merge Step of Merge Sort - O(n*log n) Time and O(n) Space
We can use merge sort to count the inversions in an array. First, we divide the array into two halves: left half and right half. Next, we recursively count the inversions in both halves. While merging the two halves back together, we also count how many elements from the left half array are greater than elements from the right half array, as these represent cross inversions (i.e., element from the left half of the array is greater than an element from the right half during the merging process in the merge sort algorithm). Finally, we sum the inversions from the left half, right half, and the cross inversions to get the total number of inversions in the array. This approach efficiently counts inversions while sorting the array.
Let's understand the above intuition in more detailed form, as we get to know that we have to perform the merge sort on the given array. Below images represents dividing and merging steps of merge sort.
During each merging step of the merge sort algorithm, we count cross inversions by comparing elements from the left half of the array with those from the right half. If we find an element arr[i] in the left half that is greater than an element arr[j] in the right half, we can conclude that all elements after i in the left half will also be greater than arr[j]. This allows us to count multiple inversions at once. Let's suppose if there are k elements remaining in the left half after i, then there are k cross inversions for that particular arr[j]. The rest of the merging process continues as usual, where we combine the two halves into a sorted array. This efficient counting method significantly reduces the number of comparisons needed, enhancing the overall performance of the inversion counting algorithm.
Below Illustration represents the cross inversion of a particular step during the merging process in the merge sort algorithm:
C++
// C++ program to Count Inversions in an array using merge sort
#include <iostream>
#include <vector>
using namespace std;
// This function merges two sorted subarrays arr[l..m] and arr[m+1..r]
// and also counts inversions in the whole subarray arr[l..r]
int countAndMerge(vector<int>& arr, int l, int m, int r) {
// Counts in two subarrays
int n1 = m - l + 1, n2 = r - m;
// Set up two vectors for left and right halves
vector<int> left(n1), right(n2);
for (int i = 0; i < n1; i++)
left[i] = arr[i + l];
for (int j = 0; j < n2; j++)
right[j] = arr[m + 1 + j];
// Initialize inversion count (or result) and merge two halves
int res = 0;
int i = 0, j = 0, k = l;
while (i < n1 && j < n2) {
// No increment in inversion count if left[] has a
// smaller or equal element
if (left[i] <= right[j])
arr[k++] = left[i++];
// If right is smaller, then it is smaller than n1-i
// elements because left[] is sorted
else {
arr[k++] = right[j++];
res += (n1 - i);
}
}
// Merge remaining elements
while (i < n1)
arr[k++] = left[i++];
while (j < n2)
arr[k++] = right[j++];
return res;
}
// Function to count inversions in the array
int countInv(vector<int>& arr, int l, int r){
int res = 0;
if (l < r) {
int m = (r + l) / 2;
// Recursively count inversions in the left and
// right halves
res += countInv(arr, l, m);
res += countInv(arr, m + 1, r);
// Count inversions such that greater element is in
// the left half and smaller in the right half
res += countAndMerge(arr, l, m, r);
}
return res;
}
int inversionCount(vector<int> &arr) {
int n = arr.size();
return countInv(arr, 0, n-1);
}
int main(){
vector<int> arr = {4, 3, 2, 1};
cout << inversionCount(arr);
return 0;
}
C
// C program to Count Inversions in an array using merge sort
#include <stdio.h>
// This function merges two sorted subarrays arr[l..m] and arr[m+1..r]
// and also counts inversions in the whole subarray arr[l..r]
int countAndMerge(int arr[], int l, int m, int r) {
// Counts in two subarrays
int n1 = m - l + 1, n2 = r - m;
// Set up two arrays for left and right halves
int left[n1], right[n2];
for (int i = 0; i < n1; i++)
left[i] = arr[i + l];
for (int j = 0; j < n2; j++)
right[j] = arr[m + 1 + j];
// Initialize inversion count (or result)
// and merge two halves
int res = 0;
int i = 0, j = 0, k = l;
while (i < n1 && j < n2) {
// No increment in inversion count
// if left[] has a smaller or equal element
if (left[i] <= right[j])
arr[k++] = left[i++];
// If right is smaller, then it is smaller than n1-i
// elements because left[] is sorted
else {
arr[k++] = right[j++];
res += (n1 - i);
}
}
// Merge remaining elements
while (i < n1)
arr[k++] = left[i++];
while (j < n2)
arr[k++] = right[j++];
return res;
}
// Function to count inversions in the array
int countInv(int arr[], int l, int r) {
int res = 0;
if (l < r) {
int m = (r + l) / 2;
// Recursively count inversions
// in the left and right halves
res += countInv(arr, l, m);
res += countInv(arr, m + 1, r);
// Count inversions such that greater element is in
// the left half and smaller in the right half
res += countAndMerge(arr, l, m, r);
}
return res;
}
int inversionCount(int arr[], int n) {
return countInv(arr, 0, n - 1);
}
int main() {
int arr[] = {4, 3, 2, 1};
int n = sizeof(arr) / sizeof(arr[0]);
printf("%d", inversionCount(arr, n));
return 0;
}
Java
// Java program to Count Inversions in an array using merge sort
import java.util.*;
class GfG {
// This function merges two sorted subarrays arr[l..m] and arr[m+1..r]
// and also counts inversions in the whole subarray arr[l..r]
static int countAndMerge(int[] arr, int l, int m, int r) {
// Counts in two subarrays
int n1 = m - l + 1, n2 = r - m;
// Set up two arrays for left and right halves
int[] left = new int[n1];
int[] right = new int[n2];
for (int i = 0; i < n1; i++)
left[i] = arr[i + l];
for (int j = 0; j < n2; j++)
right[j] = arr[m + 1 + j];
// Initialize inversion count (or result)
// and merge two halves
int res = 0;
int i = 0, j = 0, k = l;
while (i < n1 && j < n2) {
// No increment in inversion count
// if left[] has a smaller or equal element
if (left[i] <= right[j])
arr[k++] = left[i++];
// If right is smaller, then it is smaller than n1-i
// elements because left[] is sorted
else {
arr[k++] = right[j++];
res += (n1 - i);
}
}
// Merge remaining elements
while (i < n1)
arr[k++] = left[i++];
while (j < n2)
arr[k++] = right[j++];
return res;
}
// Function to count inversions in the array
static int countInv(int[] arr, int l, int r) {
int res = 0;
if (l < r) {
int m = (r + l) / 2;
// Recursively count inversions
// in the left and right halves
res += countInv(arr, l, m);
res += countInv(arr, m + 1, r);
// Count inversions such that greater element is in
// the left half and smaller in the right half
res += countAndMerge(arr, l, m, r);
}
return res;
}
static int inversionCount(int[] arr) {
return countInv(arr, 0, arr.length - 1);
}
public static void main(String[] args) {
int[] arr = {4, 3, 2, 1};
System.out.println(inversionCount(arr));
}
}
Python
# Python program to Count Inversions in an array using merge sort
# This function merges two sorted subarrays arr[l..m] and arr[m+1..r]
# and also counts inversions in the whole subarray arr[l..r]
def countAndMerge(arr, l, m, r):
# Counts in two subarrays
n1 = m - l + 1
n2 = r - m
# Set up two lists for left and right halves
left = arr[l:m + 1]
right = arr[m + 1:r + 1]
# Initialize inversion count (or result)
# and merge two halves
res = 0
i = 0
j = 0
k = l
while i < n1 and j < n2:
# No increment in inversion count
# if left[] has a smaller or equal element
if left[i] <= right[j]:
arr[k] = left[i]
i += 1
else:
arr[k] = right[j]
j += 1
res += (n1 - i)
k += 1
# Merge remaining elements
while i < n1:
arr[k] = left[i]
i += 1
k += 1
while j < n2:
arr[k] = right[j]
j += 1
k += 1
return res
# Function to count inversions in the array
def countInv(arr, l, r):
res = 0
if l < r:
m = (r + l) // 2
# Recursively count inversions
# in the left and right halves
res += countInv(arr, l, m)
res += countInv(arr, m + 1, r)
# Count inversions such that greater element is in
# the left half and smaller in the right half
res += countAndMerge(arr, l, m, r)
return res
def inversionCount(arr):
return countInv(arr, 0, len(arr) - 1)
if __name__ == "__main__":
arr = [4, 3, 2, 1]
print(inversionCount(arr))
C#
// C# program to Count Inversions in an array using merge sort
using System;
using System.Collections.Generic;
class GfG {
// This function merges two sorted subarrays arr[l..m] and arr[m+1..r]
// and also counts inversions in the whole subarray arr[l..r]
static int countAndMerge(int[] arr, int l, int m, int r) {
// Counts in two subarrays
int n1 = m - l + 1, n2 = r - m;
// Set up two arrays for left and right halves
int[] left = new int[n1];
int[] right = new int[n2];
for (int x = 0; x < n1; x++)
left[x] = arr[x + l];
for (int x = 0; x < n2; x++)
right[x] = arr[m + 1 + x];
// Initialize inversion count (or result)
// and merge two halves
int res = 0;
int i = 0, j = 0, k = l;
while (i < n1 && j < n2) {
// No increment in inversion count
// if left[] has a smaller or equal element
if (left[i] <= right[j])
arr[k++] = left[i++];
else {
arr[k++] = right[j++];
res += (n1 - i);
}
}
// Merge remaining elements
while (i < n1)
arr[k++] = left[i++];
while (j < n2)
arr[k++] = right[j++];
return res;
}
// Function to count inversions in the array
static int countInv(int[] arr, int l, int r) {
int res = 0;
if (l < r) {
int m = (r + l) / 2;
// Recursively count inversions
// in the left and right halves
res += countInv(arr, l, m);
res += countInv(arr, m + 1, r);
// Count inversions such that greater element is in
// the left half and smaller in the right half
res += countAndMerge(arr, l, m, r);
}
return res;
}
static int inversionCount(int[] arr) {
return countInv(arr, 0, arr.Length - 1);
}
static void Main() {
int[] arr = {4, 3, 2, 1};
Console.WriteLine(inversionCount(arr));
}
}
JavaScript
// JavaScript program to Count Inversions in an array using merge sort
// This function merges two sorted subarrays arr[l..m] and arr[m+1..r]
// and also counts inversions in the whole subarray arr[l..r]
function countAndMerge(arr, l, m, r) {
// Counts in two subarrays
let n1 = m - l + 1, n2 = r - m;
// Set up two arrays for left and right halves
let left = arr.slice(l, m + 1);
let right = arr.slice(m + 1, r + 1);
// Initialize inversion count (or result)
// and merge two halves
let res = 0;
let i = 0, j = 0, k = l;
while (i < n1 && j < n2) {
// No increment in inversion count
// if left[] has a smaller or equal element
if (left[i] <= right[j])
arr[k++] = left[i++];
else {
arr[k++] = right[j++];
res += (n1 - i);
}
}
// Merge remaining elements
while (i < n1)
arr[k++] = left[i++];
while (j < n2)
arr[k++] = right[j++];
return res;
}
// Function to count inversions in the array
function countInv(arr, l, r) {
let res = 0;
if (l < r) {
let m = Math.floor((r + l) / 2);
// Recursively count inversions
// in the left and right halves
res += countInv(arr, l, m);
res += countInv(arr, m + 1, r);
// Count inversions such that greater element is in
// the left half and smaller in the right half
res += countAndMerge(arr, l, m, r);
}
return res;
}
function inversionCount(arr) {
return countInv(arr, 0, arr.length - 1);
}
// Driver Code
let arr = [4, 3, 2, 1];
console.log(inversionCount(arr));
Note: The above code modifies (or sorts) the input array. If we want to count only inversions, we need to create a copy of the original array and perform operation on the copy array.
You may like to see:
Similar Reads
Merge Sort - Data Structure and Algorithms Tutorials Merge sort is a popular sorting algorithm known for its efficiency and stability. It follows the divide-and-conquer approach. It works by recursively dividing the input array into two halves, recursively sorting the two halves and finally merging them back together to obtain the sorted array. Merge
14 min read
Merge sort in different languages
C Program for Merge SortMerge Sort is a comparison-based sorting algorithm that works by dividing the input array into two halves, then calling itself for these two halves, and finally it merges the two sorted halves. In this article, we will learn how to implement merge sort in C language.What is Merge Sort Algorithm?Merg
3 min read
C++ Program For Merge SortMerge Sort is a comparison-based sorting algorithm that uses divide and conquer paradigm to sort the given dataset. It divides the dataset into two halves, calls itself for these two halves, and then it merges the two sorted halves.In this article, we will learn how to implement merge sort in a C++
4 min read
Java Program for Merge SortMerge Sort is a divide-and-conquer algorithm. It divides the input array into two halves, calls itself the two halves, and then merges the two sorted halves. The merge() function is used for merging two halves. The merge(arr, l, m, r) is a key process that assumes that arr[l..m] and arr[m+1..r] are
3 min read
Merge Sort in PythonMerge Sort is a Divide and Conquer algorithm. It divides input array in two halves, calls itself for the two halves and then merges the two sorted halves. The merge() function is used for merging two halves. The merge(arr, l, m, r) is key process that assumes that arr[l..m] and arr[m+1..r] are sorte
4 min read
Merge Sort using Multi-threadingMerge Sort is a popular sorting technique which divides an array or list into two halves and then start merging them when sufficient depth is reached. Time complexity of merge sort is O(nlogn).Threads are lightweight processes and threads shares with other threads their code section, data section an
14 min read
Variations of Merge Sort
3-way Merge SortMerge Sort is a divide-and-conquer algorithm that recursively splits an array into two halves, sorts each half, and then merges them. A variation of this is 3-way Merge Sort, where instead of splitting the array into two parts, we divide it into three equal parts. In traditional Merge Sort, the arra
13 min read
Iterative Merge SortGiven an array of size n, the task is to sort the given array using iterative merge sort.Examples:Input: arr[] = [4, 1, 3, 9, 7]Output: [1, 3, 4, 7, 9]Explanation: The output array is sorted.Input: arr[] = [1, 3 , 2]Output: [1, 2, 3]Explanation: The output array is sorted.You can refer to Merge Sort
9 min read
In-Place Merge SortImplement Merge Sort i.e. standard implementation keeping the sorting algorithm as in-place. In-place means it does not occupy extra memory for merge operation as in the standard case. Examples: Input: arr[] = {2, 3, 4, 1} Output: 1 2 3 4 Input: arr[] = {56, 2, 45} Output: 2 45 56 Approach 1: Mainta
15+ min read
In-Place Merge Sort | Set 2Given an array A[] of size N, the task is to sort the array in increasing order using In-Place Merge Sort. Examples: Input: A = {5, 6, 3, 2, 1, 6, 7}Output: {1, 2, 3, 5, 6, 6, 7} Input: A = {2, 3, 4, 1}Output: {1, 2, 3, 4} Approach: The idea is to use the inplace_merge() function to merge the sorted
7 min read
Merge Sort with O(1) extra space merge and O(n log n) time [Unsigned Integers Only]We have discussed Merge sort. How to modify the algorithm so that merge works in O(1) extra space and algorithm still works in O(n Log n) time. We may assume that the input values are integers only. Examples: Input : 5 4 3 2 1 Output : 1 2 3 4 5 Input : 999 612 589 856 56 945 243 Output : 56 243 589
10 min read
Merge Sort in Linked List
Find a permutation that causes worst case of Merge Sort Given a set of elements, find which permutation of these elements would result in worst case of Merge Sort.Asymptotically, merge sort always takes O(n Log n) time, but the cases that require more comparisons generally take more time in practice. We basically need to find a permutation of input eleme
12 min read
How to make Mergesort to perform O(n) comparisons in best case? As we know, Mergesort is a divide and conquer algorithm that splits the array to halves recursively until it reaches an array of the size of 1, and after that it merges sorted subarrays until the original array is fully sorted. Typical implementation of merge sort works in O(n Log n) time in all thr
3 min read
Concurrent Merge Sort in Shared Memory Given a number 'n' and a n numbers, sort the numbers using Concurrent Merge Sort. (Hint: Try to use shmget, shmat system calls).Part1: The algorithm (HOW?) Recursively make two child processes, one for the left half, one of the right half. If the number of elements in the array for a process is less
10 min read
Visualization of Merge Sort
Some problems on Merge Sort
Count Inversions of an ArrayGiven an integer array arr[] of size n, find the inversion count in the array. Two array elements arr[i] and arr[j] form an inversion if arr[i] > arr[j] and i < j.Note: Inversion Count for an array indicates that how far (or close) the array is from being sorted. If the array is already sorted
15+ min read
Count of smaller elements on right side of each element in an Array using Merge sortGiven an array arr[] of N integers, the task is to count the number of smaller elements on the right side for each of the element in the array Examples: Input: arr[] = {6, 3, 7, 2} Output: 2, 1, 1, 0 Explanation: Smaller elements after 6 = 2 [3, 2] Smaller elements after 3 = 1 [2] Smaller elements a
12 min read
Sort a nearly sorted (or K sorted) arrayGiven an array arr[] and a number k . The array is sorted in a way that every element is at max k distance away from it sorted position. It means if we completely sort the array, then the index of the element can go from i - k to i + k where i is index in the given array. Our task is to completely s
6 min read
Median of two Sorted Arrays of Different SizesGiven two sorted arrays, a[] and b[], the task is to find the median of these sorted arrays. Assume that the two sorted arrays are merged and then median is selected from the combined array.This is an extension of Median of two sorted arrays of equal size problem. Here we handle arrays of unequal si
15+ min read
Merge k Sorted ArraysGiven K sorted arrays, merge them and print the sorted output.Examples:Input: K = 3, arr = { {1, 3, 5, 7}, {2, 4, 6, 8}, {0, 9, 10, 11}}Output: 0 1 2 3 4 5 6 7 8 9 10 11 Input: k = 4, arr = { {1}, {2, 4}, {3, 7, 9, 11}, {13} }Output: 1 2 3 4 7 9 11 13Table of ContentNaive - Concatenate all and SortU
15+ min read
Merge K sorted arrays of different sizes | ( Divide and Conquer Approach )Given k sorted arrays of different length, merge them into a single array such that the merged array is also sorted.Examples: Input : {{3, 13}, {8, 10, 11} {9, 15}} Output : {3, 8, 9, 10, 11, 13, 15} Input : {{1, 5}, {2, 3, 4}} Output : {1, 2, 3, 4, 5} Let S be the total number of elements in all th
8 min read
Merge K sorted linked listsGiven k sorted linked lists of different sizes, the task is to merge them all maintaining their sorted order.Examples: Input: Output: Merged lists in a sorted order where every element is greater than the previous element.Input: Output: Merged lists in a sorted order where every element is greater t
15+ min read
Union and Intersection of two Linked List using Merge SortGiven two singly Linked Lists, create union and intersection lists that contain the union and intersection of the elements present in the given lists. Each of the two lists contains distinct node values.Note: The order of elements in output lists doesn't matter.Examples:Input: head1: 10 -> 15 -
15+ min read
Sorting by combining Insertion Sort and Merge Sort algorithmsInsertion sort: The array is virtually split into a sorted and an unsorted part. Values from the unsorted part are picked and placed at the correct position in the sorted part.Advantages: Following are the advantages of insertion sort: If the size of the list to be sorted is small, insertion sort ru
2 min read
Find array with k number of merge sort callsGiven two numbers n and k, find an array containing values in [1, n] and requires exactly k calls of recursive merge sort function. Examples: Input : n = 3 k = 3 Output : a[] = {2, 1, 3} Explanation: Here, a[] = {2, 1, 3} First of all, mergesort(0, 3) will be called, which then sets mid = 1 and call
6 min read
Difference of two Linked Lists using Merge sortGiven two Linked List, the task is to create a Linked List to store the difference of Linked List 1 with Linked List 2, i.e. the elements present in List 1 but not in List 2.Examples: Input: List1: 10 -> 15 -> 4 ->20, List2: 8 -> 4 -> 2 -> 10 Output: 15 -> 20 Explanation: In the
14 min read