Open In App

Counting inversions in an subarrays

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[], the goal is to count the number of inversions in all the sub-arrays. An inversion is a pair of indices i and j such that i > j and arr[i] < arr[j]. A sub-array from index x to y ( x<= y) consists of the element’s arr[x], arr[x+1], …, arr[y]. The array arr[] can also contain repeated elements.

Examples:

Input: arr[] = {3, 6, 1, 6, 5, 3, 9}
Output
0 0 2 2 4 7 7
0 0 1 1 3 6 6
0 0 0 0 1 3 3
0 0 0 0 1 3 3
0 0 0 0 0 1 1
0 0 0 0 0 0 0
0 0 0 0 0 0 0
Explanation
The element in the i’th row and j’th column of the output denotes the number of inversions from index i to j (inclusive). Consider i = 1 and j = 4 (assuming 0-based indexing), the number of inversions in the subarray {6, 1, 6, 5} is 3. The element pairs are (6, 1), (6, 5) and (6, 5) (from the second 6). 

Input: arr[] = {3, 2, 1}
Output:  
0 1 3
0 0 1
0 0 0
Explanation
From index 0 to 1 there is 1 inversion, from index 2 to 3 there is 1 inversion and from index 0 to 2 there are 3 inversions. The i’th row and j’th column of the output is 0 if i >= j.

Naive Approach: A naive approach is to generate all possible sub-arrays and count the number of inversions in each of the sub-arrays. 

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to count the number of
// inversions in all the sub-arrays
void findSubarrayInversions(int arr[], int n)
{
 
    int inversions[n][n];
 
    // Initializing the inversion count
    // of each subarray to 0
    // inversions[i][j] will denote
    // the number of inversions
    // from index i to index j inclusive
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            inversions[i][j] = 0;
        }
    }
 
    // Generating all subarray
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            int ans = 0;
            // counting the number of inversions
            // for a subarray
            for (int x = i; x <= j; x++) {
                for (int y = x; y <= j; y++) {
                    if (arr[x] > arr[y])
                        ans++;
                }
            }
 
            inversions[i][j] = ans;
        }
    }
 
    // Printing the number of inversions
    // of all subarrays
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << inversions[i][j] << " ";
        }
        cout << "\n";
    }
}
 
// Driver Code
int main()
{
 
    // Given Input
    int n = 7;
    int arr[n] = { 3, 6, 1, 6, 5, 3, 9 };
 
    // Function Call
    findSubarrayInversions(arr, n);
}


Java




// Java program for the above approach
class GFG{
 
// Function to count the number of
// inversions in all the sub-arrays
static void findSubarrayInversions(int arr[], int n)
{
    int [][]inversions = new int[n][n];
 
    // Initializing the inversion count
    // of each subarray to 0
    // inversions[i][j] will denote
    // the number of inversions
    // from index i to index j inclusive
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            inversions[i][j] = 0;
        }
    }
 
    // Generating all subarray
    for(int i = 0; i < n; i++)
    {
        for(int j = i; j < n; j++)
        {
            int ans = 0;
           
            // Counting the number of inversions
            // for a subarray
            for(int x = i; x <= j; x++)
            {
                for(int y = x; y <= j; y++)
                {
                    if (arr[x] > arr[y])
                        ans++;
                }
            }
            inversions[i][j] = ans;
        }
    }
 
    // Printing the number of inversions
    // of all subarrays
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            System.out.print(inversions[i][j] + " ");
        }
        System.out.println();
    }
}
 
// Driver Code
public static void main(String args[])
{
     
    // Given Input
    int n = 7;
    int []arr = { 3, 6, 1, 6, 5, 3, 9 };
 
    // Function Call
    findSubarrayInversions(arr, n);
}
}
 
// This code is contributed by SoumikMondal.


Python3




# Python3 program for the above approach
 
# Function to count the number of
# inversions in all the sub-arrays
def findSubarrayInversions(arr, n):
     
    inversions = [[0 for i in range(n)]
                     for j in range(n)]
                      
    # Initializing the inversion count
    # of each subarray to 0
    # inversions[i][j] will denote
    # the number of inversions
    # from index i to index j inclusive
    # Generating all subarray
    for i in range(0, n):
        for j in range(0, n):
            ans = 0
             
            # Counting the number of inversions
            # for a subarray
            for x in range(i, j + 1):
                for y in range(x, j + 1):
                    if (arr[x] > arr[y]):
                        ans += 1
                         
            # Print(ans)
            inversions[i][j] = ans
 
    # Printing the number of inversions
    # of all subarrays
    for i in range(0, n):
        for j in range(0, n):
            print(inversions[i][j], end = " ")
             
        print()
 
# Driver Code
 
# Given Input
n = 7
arr = [ 3, 6, 1, 6, 5, 3, 9 ]
 
# Function Call
findSubarrayInversions(arr, n)
 
# This code is contributed by amreshkumar3


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to count the number of
// inversions in all the sub-arrays
static void findSubarrayInversions(int []arr, int n)
{
 
    int [,]inversions = new int[n,n];
 
    // Initializing the inversion count
    // of each subarray to 0
    // inversions[i][j] will denote
    // the number of inversions
    // from index i to index j inclusive
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            inversions[i,j] = 0;
        }
    }
 
    // Generating all subarray
    for (int i = 0; i < n; i++)
    {
        for (int j = i; j < n; j++)
        {
            int ans = 0;
           
            // counting the number of inversions
            // for a subarray
            for (int x = i; x <= j; x++) {
                for (int y = x; y <= j; y++) {
                    if (arr[x] > arr[y])
                        ans++;
                }
            }
 
            inversions[i,j] = ans;
        }
    }
 
    // Printing the number of inversions
    // of all subarrays
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            Console.Write(inversions[i,j] + " ");
        }
        Console.WriteLine();
    }
}
 
// Driver Code
public static void Main()
{
 
    // Given Input
    int n = 7;
    int []arr = { 3, 6, 1, 6, 5, 3, 9 };
 
    // Function Call
    findSubarrayInversions(arr, n);
}
}
 
// This code is contributed by ipg2016107.


Javascript




<script>
 
// JavaScript program for the above approach
 
// Function to count the number of
// inversions in all the sub-arrays
function findSubarrayInversions(arr, n) {
 
    let inversions = new Array(n).fill(0).map(() => new Array(n));
 
    // Initializing the inversion count
    // of each subarray to 0
    // inversions[i][j] will denote
    // the number of inversions
    // from index i to index j inclusive
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            inversions[i][j] = 0;
        }
    }
 
    // Generating all subarray
    for (let i = 0; i < n; i++) {
        for (let j = i; j < n; j++) {
            let ans = 0;
            // counting the number of inversions
            // for a subarray
            for (let x = i; x <= j; x++) {
                for (let y = x; y <= j; y++) {
                    if (arr[x] > arr[y])
                        ans++;
                }
            }
 
            inversions[i][j] = ans;
        }
    }
 
    // Printing the number of inversions
    // of all subarrays
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            document.write(inversions[i][j] + " ");
        }
        document.write("<br>");
    }
}
 
// Driver Code
 
 
// Given Input
let n = 7;
let arr = [3, 6, 1, 6, 5, 3, 9];
 
// Function Call
 
findSubarrayInversions(arr, n);
 
</script>


Output: 

0 0 2 2 4 7 7 
0 0 1 1 3 6 6 
0 0 0 0 1 3 3 
0 0 0 0 1 3 3 
0 0 0 0 0 1 1 
0 0 0 0 0 0 0 
0 0 0 0 0 0 0

 

Time Complexity: O(N4)
Auxiliary Space: O(N2

Efficient Approach: The above method can be optimized a little using the method given here to find the number of inversions in a sub-array. First see some observations to solve this problem:

First create a 2d array greater[][], where greater[i][j] denotes the number of elements in the range i to j which are greater than arr[i]. Iterate over the array and for each element, find the number of elements to its right which are less than the element. This can be done using a naive approach in O(N^2).  Now to find the number of inversions in a range say x to y, the answer will be greater[x][y] + greater[x+1][y] + … + greater[y-1][y] + greater[y][y].

With the greater[][] table this value can be calculated in O(n) for each sub-array resulting in a complexity of O(n^3).(There are O(n^2) sub-array, and it takes O(n) time to compute the number of inversions in each sub-array). To find this value in O(1) each time build a prefix sum table from the greater[][] table where prefix[i][j] denotes the value of greater[0][j] + greater[1][j] + … + greater[i][j]. This table can also be built in O(N^2) time. Now the answer for each sub-array from x to y (inclusive) would become prefix[y][y] – prefix[x-1][y] if x >= 1 and prefix[y][y] if x = 0.

Follow the step below to solve this problem:

  • Initialize arrays greater[][] to store where greater[i][j] denotes the number of elements in the range i to j which are greater than arr[i], prefix[][] to store prefix sum for sub-array and inversions[][] to store the number of inversions.
  • Iterate in a range[0, N-1] using a variable i:
    • Iterate in a range[i+1, N-1] using a variable j:
      • Update greater[i][j] as greater[i][j-1]
      • If arr[i] is greater than arr[j], then Increment greater[i][j] by 1.
  • Iterate in a range[0, N-1] using a variable i:
    • Update prefix[0][j] as greater[0][j]
    • Iterate in a range[1, N-1] using a variable j and update prefix[i][j] as prefix[i-1][j] + greater[i][j].
  • Iterate in a range[0, N-1] using a variable i:
    • Iterate in a range[i, N-1] using a variable j:
      • If i = 0, then update inversions[i][j] as prefix[j][j]
      • Otherwise, update inversions[i][j] as prefix[j][j] + prefix[i-1][j].
  • After completing the above steps, print inversions[][] array as the answer.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to count the number of
// inversions in all the sub-arrays
void findSubarrayInversions(int arr[], int n)
{
 
    int greater[n][n];
    int prefix[n][n];
    int inversions[n][n];
 
    // Initializing the arrays to 0
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            greater[i][j] = 0;
            prefix[i][j] = 0;
            inversions[i][j] = 0;
        }
    }
 
    // For each pair of indices i and j
    // calculating the number of elements
    // from i to j inclusive which are
    // greater than arr[i]
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            greater[i][j] = greater[i][j - 1];
            if (arr[i] > arr[j])
                greater[i][j]++;
        }
    }
 
    // Building the prefix table.
    // Prefix[i][j] denotes the sum of
    // greater[0][j], greater[1][j] ... greater[i][j]
    for (int j = 0; j < n; j++) {
        prefix[0][j] = greater[0][j];
        for (int i = 1; i < n; i++) {
            prefix[i][j] = prefix[i - 1][j] + greater[i][j];
        }
    }
 
    // Calculating the inversion count for
    // each subarray using the prefix table
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            if (i == 0)
                inversions[i][j] = prefix[j][j];
            else
                inversions[i][j] = prefix[j][j]
                                   - prefix[i - 1][j];
        }
    }
 
    // Printing the values of the number
    // of inversions in each subarray
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << inversions[i][j] << " ";
        }
        cout << "\n";
    }
}
 
// Driver Code
int main()
{
 
    // Given Input
    int n = 7;
    int arr[n] = { 3, 6, 1, 6, 5, 3, 9 };
 
    // Function Call
    findSubarrayInversions(arr, n);
}


Java




/*package whatever //do not write package name here */
import java.io.*;
class GFG {
 
  // Function to count the number of
  // inversions in all the sub-arrays
  static void findSubarrayInversions(int arr[], int n)
  {
 
    int greater[][] = new int[n][n];
    int prefix[][] = new int[n][n];
    int inversions[][] = new int[n][n];
 
    // Initializing the arrays to 0
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        greater[i][j] = 0;
        prefix[i][j] = 0;
        inversions[i][j] = 0;
      }
    }
 
    // For each pair of indices i and j
    // calculating the number of elements
    // from i to j inclusive which are
    // greater than arr[i]
    for (int i = 0; i < n; i++) {
      for (int j = i + 1; j < n; j++) {
        greater[i][j] = greater[i][j - 1];
        if (arr[i] > arr[j])
          greater[i][j]++;
      }
    }
 
    // Building the prefix table.
    // Prefix[i][j] denotes the sum of
    // greater[0][j], greater[1][j] ... greater[i][j]
    for (int j = 0; j < n; j++) {
      prefix[0][j] = greater[0][j];
      for (int i = 1; i < n; i++) {
        prefix[i][j] = prefix[i - 1][j] + greater[i][j];
      }
    }
 
    // Calculating the inversion count for
    // each subarray using the prefix table
    for (int i = 0; i < n; i++) {
      for (int j = i; j < n; j++) {
        if (i == 0)
          inversions[i][j] = prefix[j][j];
        else
          inversions[i][j] = prefix[j][j]
          - prefix[i - 1][j];
      }
    }
 
    // Printing the values of the number
    // of inversions in each subarray
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        System.out.print(inversions[i][j]+" ");
      }
      System.out.println();
    }
  }
 
  public static void main (String[] args) {
    int n = 7;
    int arr[] = { 3, 6, 1, 6, 5, 3, 9 };
 
    // Function Call
    findSubarrayInversions(arr, n);
  }
}
 
// This code is contributed by aadityaburujwale.


Python3




# Python3 program for the above approach
 
# Function to count the number of
# inversions in all the sub-arrays
def findSubarrayInversions(arr, n):
     
    # Initializing the arrays to 0
    greater = [[0 for i in range(n)]
                  for j in range(n)]
    prefix = [[0 for i in range(n)]
                 for j in range(n)]
    inversions = [[0 for i in range(n)]
                     for j in range(n)]
 
    # For each pair of indices i and j
    # calculating the number of elements
    # from i to j inclusive which are
    # greater than arr[i]
    for i in range(0, n):
        for j in range(i + 1, n):
            greater[i][j] = greater[i][j - 1]
             
            if (arr[i] > arr[j]):
                greater[i][j] += 1
 
    # Building the prefix table.
    # Prefix[i][j] denotes the sum of
    # greater[0][j], greater[1][j] ... greater[i][j]
    for j in range(0, n):
        prefix[0][j] = greater[0][j]
        for i in range(1, n):
            prefix[i][j] = (prefix[i - 1][j] +
                            greater[i][j])
             
    # Calculating the inversion count for
    # each subarray using the prefix table
    for i in range(0, n):
        for j in range(i, n):
            if (i == 0):
                inversions[i][j] = prefix[j][j]
            else:
                inversions[i][j] = (prefix[j][j] -
                                    prefix[i - 1][j])
 
    # Printing the values of the number
    # of inversions in each subarray
    for i in range(0, n):
        for j in range(0, n):
            print(inversions[i][j], end = " ")
             
        print()
 
# Driver Code
# Given Input
n = 7
arr = [ 3, 6, 1, 6, 5, 3, 9 ]
 
# Function Call
findSubarrayInversions(arr, n)
 
# This code is contributed by amreshkumar3


C#




using System;
public class GFG {
 
  // Function to count the number of
  // inversions in all the sub-arrays
  static void findSubarrayInversions(int[] arr, int n)
  {
 
    int[, ] greater = new int[n, n];
    int[, ] prefix = new int[n, n];
    int[, ] inversions = new int[n, n];
 
    // Initializing the arrays to 0
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        greater[i, j] = 0;
        prefix[i, j] = 0;
        inversions[i, j] = 0;
      }
    }
 
    // For each pair of indices i and j
    // calculating the number of elements
    // from i to j inclusive which are
    // greater than arr[i]
    for (int i = 0; i < n; i++) {
      for (int j = i + 1; j < n; j++) {
        greater[i, j] = greater[i, j - 1];
        if (arr[i] > arr[j])
          greater[i, j]++;
      }
    }
 
    // Building the prefix table.
    // Prefix[i][j] denotes the sum of
    // greater[0][j], greater[1][j] ... greater[i][j]
    for (int j = 0; j < n; j++) {
      prefix[0, j] = greater[0, j];
      for (int i = 1; i < n; i++) {
        prefix[i, j]
          = prefix[i - 1, j] + greater[i, j];
      }
    }
 
    // Calculating the inversion count for
    // each subarray using the prefix table
    for (int i = 0; i < n; i++) {
      for (int j = i; j < n; j++) {
        if (i == 0)
          inversions[i, j] = prefix[j, j];
        else
          inversions[i, j]
          = prefix[j, j] - prefix[i - 1, j];
      }
    }
 
    // Printing the values of the number
    // of inversions in each subarray
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        Console.Write(inversions[i, j] + " ");
      }
      Console.WriteLine();
    }
  }
 
  public static void Main(string[] args)
  {
    int n = 7;
    int[] arr = { 3, 6, 1, 6, 5, 3, 9 };
 
    // Function Call
    findSubarrayInversions(arr, n);
  }
}
 
// This code is contributed by krandeep1234.


Javascript




<script>
// Javascript program for the above approach
 
// Function to count the number of
// inversions in all the sub-arrays
function findSubarrayInversions(arr, n) {
  let greater = new Array(n).fill(0).map(() => new Array(n).fill(0));
  let prefix = new Array(n).fill(0).map(() => new Array(n).fill(0));
  let inversions = new Array(n).fill(0).map(() => new Array(n).fill(0));
 
  // Initializing the arrays to 0
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      greater[i][j] = 0;
      prefix[i][j] = 0;
      inversions[i][j] = 0;
    }
  }
 
  // For each pair of indices i and j
  // calculating the number of elements
  // from i to j inclusive which are
  // greater than arr[i]
  for (let i = 0; i < n; i++) {
    for (let j = i + 1; j < n; j++) {
      greater[i][j] = greater[i][j - 1];
      if (arr[i] > arr[j]) greater[i][j]++;
    }
  }
 
  // Building the prefix table.
  // Prefix[i][j] denotes the sum of
  // greater[0][j], greater[1][j] ... greater[i][j]
  for (let j = 0; j < n; j++) {
    prefix[0][j] = greater[0][j];
    for (let i = 1; i < n; i++) {
      prefix[i][j] = prefix[i - 1][j] + greater[i][j];
    }
  }
 
  // Calculating the inversion count for
  // each subarray using the prefix table
  for (let i = 0; i < n; i++) {
    for (let j = i; j < n; j++) {
      if (i == 0) inversions[i][j] = prefix[j][j];
      else inversions[i][j] = prefix[j][j] - prefix[i - 1][j];
    }
  }
 
  // Printing the values of the number
  // of inversions in each subarray
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      document.write(inversions[i][j] + " ");
    }
    document.write("<br>");
  }
}
 
// Driver Code
 
// Given Input
let n = 7;
let arr = [3, 6, 1, 6, 5, 3, 9];
 
// Function Call
findSubarrayInversions(arr, n);
 
// This code is contributed by saurabh_jaiswal.
</script>


Output: 

0 0 2 2 4 7 7 
0 0 1 1 3 6 6 
0 0 0 0 1 3 3 
0 0 0 0 1 3 3 
0 0 0 0 0 1 1 
0 0 0 0 0 0 0 
0 0 0 0 0 0 0

 

Time Complexity: O(N2)
Space Complexity: O(N2)

Notes-

  • Some space can be saved by building the prefix[][] table on top of the greater[][] table but the order will still remain the same.
  • It is not possible to perform better than O(N^2) if you want to find the exact count of inversions in all subarrays as the number of subarrays is always O(N^2).


Last Updated : 31 Oct, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads