Given an array arr[] of N integers. The task is to find the number of inversion. Two elements arr[i] and arr[j] form an inversion if arr[i] > arr[j] and i < j.
Examples
Input: arr[] = {8, 4, 2, 1}
Output: 6
Explanation:
Given array has six inversions:
- (8, 4): arr[0] > arr[1] and 0 < 1
- (8, 2): arr[0] > arr[2] and 0 < 2
- (8, 1): arr[0] > arr[3] and 0 < 3
- (4, 2): arr[1] > arr[2] and 1 < 2
- (4, 1): arr[1] > arr[3] and 1 < 3
- (2, 1): arr[2] > arr[3] and 2 < 3
Input: arr[] = {2, 3}
Output: 0
Explanation:
There is no such pair exists such that arr[i] > arr[j] and i < j.
We have already discussed below approaches:
- Count Inversions in an array | Set 1 (Using Merge Sort)
- Count inversions in an array | Set 2 (Using Self-Balancing BST)
- Counting Inversions using Set in C++ STL
- Count inversions in an array | Set 3 (Using BIT)
In this post, we will be discussing an approach using Ordered Set and GNU C++ PBDS.
Approach:
We will be using the function order_of_key(K) which returns number of elements strictly smaller than K in log N time.
- Insert the first element of the array in the Ordered_Set.
- For all the remaining element in arr[] do the following:
- Insert the current element in the Ordered_Set.
- Find the number of element strictly less than current element + 1 in Ordered_Set using function order_of_key(arr[i]+1).
- The difference between size of Ordered_Set and order_of_key(current_element + 1) will give the inversion count for the current element.
For Example:
arr[] = {8, 4, 2, 1} Ordered_Set S = {8} For remaining element in arr[]: At index 1, the element is 4 S = {4, 8} key = order_of_key(5) = 1 The difference between size of S and key gives the total number of inversion count for that current element. inversion_count = S.size() - key = 2 - 1 = 1 Inversion Pairs are: (8, 4) At index 2, the element is 2 S = {2, 4, 8} key = order_of_key(3) = 1 inversion_count = S.size() - key = 3 - 1 = 2 Inversion Pairs are: (8, 2) and (4, 2) At index 3, the element is 1 S = {1, 2, 4, 8} key = order_of_key(2) = 1 inversion_count = S.size() - key = 4 - 1 = 3 Inversion Pairs are: (8, 1), (4, 1) and (2, 1) Total inversion count = 1 + 2 + 3 = 6
Below is the implementation of the above approach:
C++
// Ordered set in GNU C++ based // approach for inversion count #include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace __gnu_pbds; using namespace std; // Ordered Set Tree typedef tree< int , null_type, less_equal< int >, rb_tree_tag, tree_order_statistics_node_update> ordered_set; // Returns inversion count in // arr[0..n-1] int getInvCount( int arr[], int n) { int key; // Initialise the ordered_set ordered_set set1; // Insert the first // element in set set1.insert(arr[0]); // Initialise inversion // count to zero int invcount = 0; // Finding the inversion // count for current element for ( int i = 1; i < n; i++) { set1.insert(arr[i]); // Number of elements strictly // less than arr[i]+1 key = set1.order_of_key(arr[i] + 1); // Difference between set size // and key will give the // inversion count invcount += set1.size() - key; } return invcount; } // Driver's Code int main() { int arr[] = { 8, 4, 2, 1 }; int n = sizeof (arr) / sizeof ( int ); // Function call to count // inversion cout << getInvCount(arr, n); return 0; } |
6
Time Complexity: O(Nlog N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!