I'm using TreeSet
for solving counting inversions problem. I'm using following approach which uses gnu_pbds
which works in O(logn) time.
Algorithm
- 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 functionorder_of_key
(arr[i]+1). - The difference between size of
Ordered_Set
andorder_of_key
(current_element + 1) will given the inversion count for the current element.
You can read more about this algorithm here.
For
order_of_key
method I'm usingTreeSet
's headset(k) method for calculation.
My code
public class Solution {
static int order_of_key(TreeSet<Integer> s, int k)
{
return s.headSet(k, true).size();
}
public int solve(ArrayList<Integer> a) {
TreeSet<Integer> s = new TreeSet<>();
s.add(a.get(0));
int invcount = 0;
for(int i = 1; i < a.size(); i++)
{
s.add(a.get(i));
int key = order_of_key(s, a.get(i) + 1);
// if (i + 1 == a.size()) key--;
invcount += s.size() - key;
// System.out.println(s+" " + (a.get(i) + 1) + " " + key + " " + invcount);
}
return invcount;
}
}
Respective C++ Code
// 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]
void print(ordered_set s, int n){
for(int i = 0; i < n; i++)
{
// printf("%d ",s[i]); // <<endl;
cout << *(s.find_by_order(i))
<< " ";
}
// cout << endl;
}
int getInvCount(int arr[], int n)
{
int key;
// Intialise the ordered_set
ordered_set set1;
// Insert the first
// element in set
set1.insert(arr[0]);
// Intialise 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;
print(set1, n);
cout << arr[i] + 1 << " ";
cout << key << " ";
cout << " " << invcount << endl;
}
return invcount;
}
// Driver's Code
int main()
{
int arr[] = { 32, 35, 43, 1, 38, 39, 42 };
int n = sizeof(arr) / sizeof(int);
cout << n << endl;
// Function call to count
// inversion
cout << getInvCount(arr, n);
return 0;
}
Observations
- my solution works for all test cases but for some trivial test cases it returns the
1- inversion count
. If I changed the working oforder_of_key
to the following it breaks some other test cases.
int order_of_key(TreeSet<Integer> s, int k)
{
if(s.contains(k))
return s.headSet(k).size();
else
return s.headSet(k, true).size();
}
- but the
gnu_pbds
works for all the time.
Please help me fix this code using TreeSet
. Also if I'm missing the some another points respect to pbds
order_of_key method then let me know.