Open In App

Inversion Count using Policy Based Data Structure

Improve
Improve
Like Article
Like
Save
Share
Report

Pre-requisite: Policy based data structure Given an array arr[], the task is to find the number of inversions for each element of the array.

Inversion Count: for an array indicates – how far (or close) the array is from being sorted. If the array is already sorted then the inversion count is 0. If the array is sorted in the reverse order then the inversion count is the maximum. Formally, Number of indices i   and j   such that arr[i] > arr[j]   and i < j   .

Examples:

Input: {5, 2, 3, 2, 3, 8, 1} Output: {0, 1, 1, 2, 1, 0, 6} Explanation: Inversion count for each elements – Element at index 0: There are no elements with less index than 0, which is greater than arr[0]. Element at index 1: There is one element with less index than 1, which is greater than 2. That is 5. Element at index 2: There is one element with less index than 2, which is greater than 3. That is 5. Element at index 3: There are two elements with less index than 3, which is greater than 2. That is 5, 3. Element at index 4: There is one element with less index than 4, which is greater than 3. That is 5. Element at index 5: There are no elements with less index than 5, which is greater than 8. Element at index 6: There are six elements with less index than 6, which is greater than 1. That is 5, 2, 3, 2, 3 Input: arr[] = {3, 2, 1} Output: {0, 1, 2}

Approach:

  • Create a policy based data structure of type pair.
  • Iterate the given array and perform the following steps –
    • Apply order_of_key({X, N+1}) for each element X where N is the size of array. Note: order_of_key is nothing but lower_bound. Also, we used N+1 because it is greater than all the indices in the array.
    • Let order_of_key comes out to be l, then the inversion count for current element will be equal to St.size() - l   which is ultimately the count of elements smaller than X and came before X in the array.
    • Insert the current element X along with its index in the policy-based data structure St. The index is inserted along with each element for its unique identification in the set and to deal with duplicates.

Below is the implementation of the above approach: 

C++

// C++ implementation to find the
// Inversion Count using Policy
// Based Data Structure
 
#include <bits/stdc++.h>
 
// Header files for policy based
// data structure which are
// to be included
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
 
using namespace __gnu_pbds;
using namespace std;
 
typedef tree<pair<int, int>, null_type,
             less<pair<int, int> >, rb_tree_tag,
             tree_order_statistics_node_update>
    new_data_set;
 
// Function to find the inversion count
// of the elements of the array
void inversionCount(int arr[], int n)
{
    int ans[n];
 
    // Making a new policy based data
    // structure which will
    // store pair<int, int>
    new_data_set St;
 
    // Loop to iterate over the elements
    // of the array
    for (int i = 0; i < n; i++) {
 
        // Now to find lower_bound of
        // the element X, we will use pair
        // as {x, n+1} to cover all the
        // elements and even the duplicates
        int cur = St.order_of_key({ arr[i],
                                    n + 1 });
 
        ans[i] = St.size() - cur;
 
        // Store element along with index
        St.insert({ arr[i], i });
    }
 
    for (int i = 0; i < n; i++) {
        cout << ans[i] << " ";
    }
    cout << "\n";
}
 
// Driver Code
int main()
{
    int arr[] = { 5, 2, 3, 2, 3, 8, 1 };
    int n = sizeof(arr) / sizeof(int);
 
    // Function Call
    inversionCount(arr, n);
 
    return 0;
}

                    

Java

import java.util.*;
import java.io.*;
import java.lang.*;
 
import java.util.AbstractMap.SimpleEntry;
import java.util.Map.Entry;
 
// Header files for policy based data structure which are to be included
import java.util.TreeSet;
 
public class GFG
{
    public static void inversionCount(int[] arr, int n)
    {
        int[] ans = new int[n];
 
        // Making a new policy based data structure which will store pair<int, int>
        TreeSet<Entry<Integer, Integer>> St = new TreeSet<>(new Comparator<Entry<Integer, Integer>>() {
            @Override
            public int compare(Entry<Integer, Integer> a, Entry<Integer, Integer> b) {
                return a.getKey().compareTo(b.getKey());
            }
        });
 
        // Loop to iterate over the elements of the array
        for (int i = 0; i < n; i++) {
 
            // Now to find lower_bound of the element X, we will use pair as {x, n+1} to cover all the
            // elements and even the duplicates
            int cur = St.headSet(new SimpleEntry<Integer, Integer>(arr[i], n+1)).size();
 
            ans[i] = St.size() - cur;
 
            // Store element along with index
            St.add(new SimpleEntry<Integer, Integer>(arr[i], i));
        }
 
        for (int i = 0; i < n; i++) {
            System.out.print(ans[i] + " ");
        }
        System.out.print("\n");
    }
 
    public static void main(String[] args) {
        int[] arr = { 5, 2, 3, 2, 3, 8, 1 };
        int n = arr.length;
 
        // Function Call
        inversionCount(arr, n);
    }
}

                    

Python3

# Python implementation to find the
# Inversion Count using Policy
# Based Data Structure
 
# Import required libraries
from collections import defaultdict
from bisect import bisect_right
 
 
# Function to find the inversion count
# of the elements of the array
def inversionCount(arr, n):
    ans = [0] * n
 
    # Making a new dictionary to store index
    # of every element
    index_dict = defaultdict(list)
 
    # Loop to iterate over the elements
    # of the array
    for i in range(n):
 
        # Find the index of the current element in
        # the sorted list of elements so far
        cur = bisect_right(index_dict[arr[i]], i)
 
        ans[i] = i - cur
 
        # Store the current element's index
        index_dict[arr[i]].append(i)
 
    for i in range(n):
        print(ans[i], end=' ')
    print()
 
 
# Driver Code
if __name__ == '__main__':
    arr = [5, 2, 3, 2, 3, 8, 1]
    n = len(arr)
 
    # Function Call
    inversionCount(arr, n)

                    

C#

using System;
 
public class Program
{
    // Binary Indexed Tree
    static int[] bit;
    static int MAX = 10000;
 
    // Function to update the Binary Indexed Tree
    static void update(int idx, int val)
    {
        // Update all the ancestors of idx
        for (; idx <= MAX; idx += idx & -idx)
            bit[idx] += val;
    }
 
    // Function to query the Binary Indexed Tree
    static int query(int idx)
    {
        int sum = 0;
        // Get the sum of all elements up to idx
        for (; idx > 0; idx -= idx & -idx)
            sum += bit[idx];
        return sum;
    }
 
    public static void InversionCount(int[] arr, int n)
    {
        // Initialize the Binary Indexed Tree
        bit = new int[MAX + 1];
        int[] ans = new int[n];
 
        for (int i = 0; i < n; i++)
        {
            // Count of elements greater than arr[i]
            int cur = query(MAX) - query(arr[i]);
 
            ans[i] = cur;
 
            // Insert the negative of arr[i] to get a reverse sorted set
            update(arr[i], 1);
        }
 
        // Print the inversion count for each element
        for (int i = 0; i < n; i++)
        {
            Console.Write(ans[i] + " ");
        }
        Console.WriteLine();
    }
 
    public static void Main()
    {
        int[] arr = { 5, 2, 3, 2, 3, 8, 1 };
        int n = arr.Length;
 
        // Call the function to calculate inversion count
        InversionCount(arr, n);
    }
}

                    

Javascript

// Function to find the inversion count
// of the elements of the array
function inversionCount(arr, n) {
  let ans = new Array(n).fill(0);
 
  // Making a new object to store index
  // of every element
  let index_dict = {};
 
  // Loop to iterate over the elements
  // of the array
  for (let i = 0; i < n; i++) {
 
    // Find the index of the current element in
    // the sorted list of elements so far
    if (arr[i] in index_dict) {
      let cur = index_dict[arr[i]].filter((index) => index < i).length;
      ans[i] = i - cur;
    } else {
      ans[i] = i;
    }
 
    // Store the current element's index
    if (arr[i] in index_dict) {
      index_dict[arr[i]].push(i);
    } else {
      index_dict[arr[i]] = [i];
    }
  }
 
  console.log(ans.join(' '));
}
 
// Driver Code
let arr = [5, 2, 3, 2, 3, 8, 1];
let n = arr.length;
 
// Function Call
inversionCount(arr, n);
 
// This code is contributed by Aditya Sharma

                    

Output
0 1 1 2 1 0 6

Time Complexity: O(N*LogN)



Last Updated : 15 Feb, 2024
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads