Count Inversions in an array

Inversion Count for an array indicates – how far (or close) the array is from being sorted. If array is already sorted then inversion count is 0. If array is sorted in reverse order that inversion count is the maximum.
Formally speaking, two elements a[i] and a[j] form an inversion if a[i] > a[j] and i < j

Example:
The sequence 2, 4, 1, 3, 5 has three inversions (2, 1), (4, 1), (4, 3).

METHOD 1 (Simple)
For each element, count number of elements which are on right side of it and are smaller than it.

int getInvCount(int arr[], int n)
{
  int inv_count = 0;
  int i, j;

  for(i = 0; i < n - 1; i++)
    for(j = i+1; j < n; j++)
      if(arr[i] > arr[j])
        inv_count++;

  return inv_count;
}

/* Driver progra to test above functions */
int main(int argv, char** args)
{
  int arr[] = {1, 20, 6, 4, 5};
  printf(" Number of inversions are %d \n", getInvCount(arr, 5));
  getchar();
  return 0;
}

Time Complexity: O(n^2)



METHOD 2(Enhance Merge Sort)
Suppose we know the number of inversions in the left half and right half of the array (let be inv1 and inv2), what kinds of inversions are not accounted for in Inv1 + Inv2? The answer is – the inversions we have to count during the merge step. Therefore, to get number of inversions, we need to add number of inversions in left subarray, right subarray and merge().

inv_count1
How to get number of inversions in merge()?
In merge process, let i is used for indexing left sub-array and j for right sub-array. At any step in merge(), if a[i] is greater than a[j], then there are (mid – i) inversions. because left and right subarrays are sorted, so all the remaining elements in left-subarray (a[i+1], a[i+2] … a[mid]) will be greater than a[j]

inv_count2

The complete picture:
inv_count3

Implementation:

#include <stdio.h>
#include <stdlib.h>
 
int  _mergeSort(int arr[], int temp[], int left, int right);
int merge(int arr[], int temp[], int left, int mid, int right);
 
/* This function sorts the input array and returns the
   number of inversions in the array */
int mergeSort(int arr[], int array_size)
{
    int *temp = (int *)malloc(sizeof(int)*array_size);
    return _mergeSort(arr, temp, 0, array_size - 1);
}
 
/* An auxiliary recursive function that sorts the input array and
  returns the number of inversions in the array. */
int _mergeSort(int arr[], int temp[], int left, int right)
{
  int mid, inv_count = 0;
  if (right > left)
  {
    /* Divide the array into two parts and call _mergeSortAndCountInv()
       for each of the parts */
    mid = (right + left)/2;
 
    /* Inversion count will be sum of inversions in left-part, right-part
      and number of inversions in merging */
    inv_count  = _mergeSort(arr, temp, left, mid);
    inv_count += _mergeSort(arr, temp, mid+1, right);
 
    /*Merge the two parts*/
    inv_count += merge(arr, temp, left, mid+1, right);
  }
  return inv_count;
}
 
/* This funt merges two sorted arrays and returns inversion count in
   the arrays.*/
int merge(int arr[], int temp[], int left, int mid, int right)
{
  int i, j, k;
  int inv_count = 0;
 
  i = left; /* i is index for left subarray*/
  j = mid;  /* i is index for right subarray*/
  k = left; /* i is index for resultant merged subarray*/
  while ((i <= mid - 1) && (j <= right))
  {
    if (arr[i] <= arr[j])
    {
      temp[k++] = arr[i++];
    }
    else
    {
      temp[k++] = arr[j++];
 
     /*this is tricky -- see above explanation/diagram for merge()*/
      inv_count = inv_count + (mid - i);
    }
  }
 
  /* Copy the remaining elements of left subarray
   (if there are any) to temp*/
  while (i <= mid - 1)
    temp[k++] = arr[i++];
 
  /* Copy the remaining elements of right subarray
   (if there are any) to temp*/
  while (j <= right)
    temp[k++] = arr[j++];
 
  /*Copy back the merged elements to original array*/
  for (i=left; i <= right; i++)
    arr[i] = temp[i];
 
  return inv_count;
}
 
/* Driver progra to test above functions */
int main(int argv, char** args)
{
  int arr[] = {1, 20, 6, 4, 5};
  printf(" Number of inversions are %d \n", mergeSort(arr, 5));
  getchar();
  return 0;
}

Note that above code modifies (or sorts) the input array. If we want to count only inversions then we need to create a copy of original array and call mergeSort() on copy.

Time Complexity:
O(nlogn)
Algorithmic Paradigm: Divide and Conquer


References:

http://www.cs.umd.edu/class/fall2009/cmsc451/lectures/Lec08-inversions.pdf
http://www.cp.eng.chula.ac.th/~piak/teaching/algo/algo2008/count-inv.htm

Please write comments if you find any bug in the above program/algorithm or other ways to solve the same problem.





  • Paramvir Singh

    everybody who is facing with the doubt that inversions should be mid-1+j is correct. It’s just that see the merge the function argument passed is mid+1 not mid. Hope this helps.

  • Rahul

    Its fine! Sorry

  • Rahul

    It should be j=mid+1

  • Rahul

    I am in a doubt..there should be mid-i+1 inversions.

    • Rahul

      or j should point to mid+1????

  • alam01

    If we just need the inversion count then what is the need of array ‘temp’?
    Do we need it?

  • Akshay Srinivas

    i wrote following algorithm, let me know if its good one

    #include
    static int *start_address=0;
    static int size = 0;
    int inc = 0;
    int inversion(int *arr, int num, int n)
    {
    if(n == 0) {
    if(num > arr[0]) {
    return 1;
    }
    return 0;
    }
    inc += inversion(arr, num, n/2);
    if(n %2 != 0 && n > 1) {
    if(num > arr[n-1]) {
    inc++;
    }
    }
    if(n%2 && n != 1) {
    inc += inversion(arr + n , num, n/2);
    } else {
    int index = 0;
    index = (arr +n) – start_address;
    if(index 1) {
    int index = 0;
    index = (arr +n +n -1) – start_address;

    if(index (arr + n)[n-1])
    inc += 1;
    }
    return 0;
    }

    int main()
    {
    int i =0, inverse = 0;
    // int arr[]={100,0,1,23,25};
    int arr[]={11,100,0,1,3,20,4,7,0,2,24,5,9,25,11,8,45,78,90,14,21};
    int n =0;
    size = n = sizeof(arr)/sizeof(arr[0]);
    start_address = arr;
    for(i=0;i<n;i++){
    printf("%d ", arr[i]);
    }
    printf("n");

    printf("size %dn", size);

    for(i=0;i<n-1;i++) {
    if((n-1-i)%2)
    inversion(arr+i + 1,arr[i],(n-i)/2);
    else
    inversion(arr+i + 1,arr[i],(n-1-i)/2);
    }
    printf("total inversions %dn", inc);
    }

  • feroz

    how can i do method one in 2d array c#

  • tczf1128

    ‘inv_count = _mergeSort(arr, temp, left, mid);’ should be ‘+=’

    • tczf1128

      you are right.sorry

  • Murali

    We can solve this in O(n) using a stack.

    • Upen

      we can solve it by using stack but can’t in O(n) time it will cost us O(n^2) …. give me your algorithm if you really think we can solve it in O(n) using stack

  • kd111

    //Simple modification to mergeSort algorithm

    #include
    #include

    int count = 0;

    void mergeAndCount(int *A , int low , int mid , int high){
    int n1 = mid – low + 1;
    int n2 = high – low;
    int *L = (int *) malloc(sizeof(int)*n1);
    int *R = (int *) malloc(sizeof(int)*n2);
    int i , j , k;
    for(i = 0 ; i < n1 ; i++)
    L[i] = A[low + i];
    for(j = 0 ; j < n2 ; j++)
    R[j] = A[mid + 1 + j];
    i = 0;
    j = 0;
    k = low;
    while(i < n1 && j < n2){
    if(L[i] <= R[j]){
    A[k] = L[i];
    i++;
    k++;
    }
    else{
    count = count + n1 – i;
    A[k] = R[j];
    j++;
    k++;
    }
    }
    while(i < n1){
    A[k] = L[i];
    i++;
    k++;
    }
    while(j < n2){
    A[k] = R[j];
    j++;
    k++;
    }
    free(L);
    free(R);
    }

    void mergeSort(int *A , int low , int high){
    if( low < high ){
    int mid = low + (high – low)/2;
    mergeSort(A , low , mid);
    mergeSort(A , mid + 1 , high);
    mergeAndCount(A , low , mid ,high);
    }
    }

    int main(){
    int A[] = {6,5,4,3,2,1};
    int size = sizeof(A)/sizeof(A[0]);
    printf("Given array :nt");
    int i;
    for(i = 0 ; i < size ; i++)
    printf("%d ",A[i]);
    mergeSort(A , 0 , size – 1);
    printf("nno. of inversions : %dn",count);
    return 0;
    }

  • Marsha Donna

    @geeksforgeeks although not optimal..is the following progm correct to count the number of inversions using bubble sort..just to clarify the concept..

    #include

    int bubble(int arr[],int n)
    {
    int i, j,temp,k,inv_count=0;

    for(i = 0; i <= n – 2; i++)
    for(j = 0; j arr[j+1])
    {
    temp=arr[j];
    arr[j]=arr[j+1];
    arr[j+1]=temp;
    inv_count++;
    }
    return inv_count;
    }

    void main()
    {
    int k,count_inv;
    int myarray[] = {50,40,30,20,10};
    count_inv=bubble(myarray,5);
    for(k=0;k<5;k++)
    printf("sorted array is %dn",myarray[k]);
    printf("the number of inversions is %d",count_inv);
    }

  • Guest

    @geeksforgeeks:disqus although not optimal..is the following progm correct to count the number of inversions using bubble sort..just to clarify the concept..

    #include

    int bubble(int arr[],int n)
    {
    int i, j,temp,k,inv_count=0;

    for(i = 0; i <= n – 2; i++)
    {for(j = 0; j arr[j+1])
    {
    printf(“n%dt%dn”,arr[j],arr[j+1]);
    temp=arr[j];
    arr[j]=arr[j+1];
    arr[j+1]=temp;
    inv_count++;
    // for(k=0;k<n;k++)
    // printf("%d",arr[k]);
    }

    }
    printf("nn");
    for(k=0;k<n;k++)
    printf("%dt",arr[k]);printf("nn");
    }
    return inv_count;
    }

    void main()
    {int k,count_inv;
    int myarray[] = {50,40,30,20,10};
    count_inv=bubble(myarray,5);
    for(k=0;k<5;k++)
    printf("sorted array is %dn",myarray[k]);
    printf("the number of inversions is %d",count_inv);
    }

  • Mohit Garg

    I think there exists a simpler solution
    sort the array
    e.g. 4,5,6,1,2,3 becomes 1,2,3,4,5,6
    find the displacement for a given element e.g. 4 which was initially at 0 is now at index 3. Thus displacement is 3.

    Total number of inversions should be sum of all the displacement towards right.
    Only 4,5,6 are displaced right, total = 3+3+3 = 9

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
    • piyush

      Try using the same technique on 4,5,6,1,3,2:
      Your answer would still be 3+3+3=9, however the correct answer is 10.

      Its the not displacement towards right that counts, but the relative displacements of elements. e.g. 3 relative to 2 is swapped => add 1, and so on .

  • crazy
     
    #include<stdio.h>
    #define INF 19999999
    long long total;
    void merge(int a[],int p,int q,int r)
    {
        int n1,n2,i,k,j;
        n1=(q-p)+1;
        n2=(r-q);
        int left[n1+2],right[n2+2];
        for(i=1;i<=n1;i++)
         left[i]=a[p+i-1];
        for(i=1;i<=n2;i++)
         right[i]=a[q+i];
        left[n1+1]=right[n2+1]=INF;
        i=j=1;
        for(k=p;k<=r;k++)
        {
            if(left[i]<=right[j])
             a[k]=left[i++];
            else
            {
             total+=(n1-(i-1));
             a[k]=right[j++];
            }
        }
    }
    void mergesort(int a[],int p,int r)
    {
        int q;
        if(p<r)
        {
            q=(p+r)/2;
            mergesort(a,p,q);
            mergesort(a,q+1,r);
            merge(a,p,q,r);
        }
    }
    int main(int argv, char** args)
    {
      int arr[] = {1, 20, 6, 4, 5};
      mergeSort(arr,0,4);
      printf(" Number of inversions are %d \n",total);
      getchar();
      return 0;
    }
    /* Paste your code here (You may delete these lines if not writing code) */
     
  • Venkatesh B

    for the algorithm given by geeks for geeks, for this input 4,5,6,1,2,3 number of inversions are 9, is that correct?

    • Swapnil R Mehta

      Yes its correct.
      As inversions: (4,1),(4,2),(4,3),(5,1),(5,2),(5,3),(6,1)(6,2),(6,3).

    • ljk

      Is this venkatesh basker?

    • Venkatesh Fan

      Are u the famous Venkatesh B?

  • shivi
     
    #include <algorithm>
    #include <cstdio>
    #include<shiviheaders.h>
    #include <cstring>
    using namespace std;
    
    typedef long long llong;
    const int MAXN = 500020;
    llong tree[MAXN], A[MAXN], B[MAXN];
    
    llong read(int idx)
    {
        llong sum = 0;
        while (idx > 0)
        {
            sum += tree[idx];
            idx -= (idx & -idx);
        }
        return sum;
    }
    
    void update(int idx ,llong val)
    {
        while (idx <= MAXN)
        {
            tree[idx] += val;
            idx += (idx & -idx);
        }
    }
    
    int main()
    {
        int N,t;
        // scanf("%d",&t);
        t=1;
        while(t--)
        {
    		 scanf("%d",&N);      
            memset(tree, 0, sizeof(tree));
            for(int i = 0; i < N; ++i)
            {
                scanf("%lld",&A[i]);
                B[i] = A[i];
            }
            
            sort(B, B + N);
            
            for(int i = 0; i < N; ++i)
            {
                int rank = int(lower_bound(B, B + N, A[i]) - B);
                A[i] = rank + 1;
            }
            
            
            
            llong inv_count = 0;
            
            for(int i = N - 1; i >= 0; --i)
            {
                llong x = read(A[i] - 1);
                inv_count += x;
                update(A[i], 1);
            }
            printf("%lld\n",inv_count);
        }
        return 0;
    }
     
  • ajiteshpathak

    Not sure if any of the above methods have similar implementation but here is my approach. Basically I am using I ,j where I holds the iterator for every element in the array and J just iterates all elements before it.

    int inversionCount(int *arr, int n)
    {
    int i = 0, j = 1;
    int count = 0;

    while (i < n - 1)
    {
    if (arr[j] > arr[i] && j > i)
    {
    // Already sorted
    j++;
    }
    else if (arr[j] < arr[i] && j > i)
    {
    printf(” (%d, %d) “, arr[i], arr[j]);
    j++;
    count++;
    }

    if (j == n)
    {
    i++;
    j = i + 1;
    }
    }

    return count;
    }

  • lotus

    Why can’t we just store sorted array and count how many numbers in the original array are not in their expected position.

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
    • dew

      @GeeksforGeeks Please let us know if there is any mistake in this logic. Creating a temp array in which the elements are sorted. then finding the no of elements that are not in their correct position

      • Priso

        Consider an sorted array (1,2,3,4) where inversion is 0
        now lets swap 1 and 4 so the array is (4,2,3,1)
        and the numbers which are not in their expected positions = 2 (number 4 and number 1)

        But the number of inversions = 5 i.e., {(4,2),(4,3),(4,1),(2,1),(3,1)}

         
        /* Paste your code here (You may delete these lines if not writing code) */
         
  • mukesh gupta

    void inversion(int a[ ],int n)
    {
    if(n>1){
    int b[n/2],c[n-n/2],i,j=0,k,m;
    for(i=0;i<n/2;i++)
    b[i]=a[i];
    for(i=n/2;i<n;i++)
    { c[j]=a[i];
    j++;}
    inversion(b,n/2);
    inversion(c,n-n/2);
    i=0;
    j=0;
    k=0;
    while(i<n/2 && j<(n-n/2))
    { if(b[i]<c[j])
    { a[k]=b[i];
    i++;}
    else
    { a[k]=c[j];
    j++;
    for(m=i;m<n/2;m++)
    inver++; }
    k++;
    }
    if(i==n/2)
    for(i=j;i<n-n/2;i++)
    a[k++]=c[i];
    else if(j==n-n/2)
    for(j=i;j<n/2;j++)
    a[k++]=b[j];
    }
    }

  • mukesh gupta

    void inversion(int a[ ],int n)
    {
    if(n>1){
    int b[n/2],c[n-n/2],i,j=0,k,m;
    for(i=0;i<n/2;i++)
    b[i]=a[i];
    for(i=n/2;i<n;i++)
    { c[j]=a[i];
    j++;}
    inversion(b,n/2);
    %2

  • bartender

    If mid = (left+right)/2
    The number of inversions should be mid+1-i.
    As all elements from A[i] to A[mid] are less than A[j]
    which is mid+1-i.

    But the code works out as we pass mid+1 into the merge function.So, here mid= (left+right)/2+1 i.e. as explained in code, pointing to the first element in the second sub-array.

    • coderAce

      You’re right. @Moderators, you should highlight this in the main article.

  • Ankit Malhotra

    Earlier code was using extra memory. However using array rotation, this can be made inplace as follows :

     
    
    #include <iostream>
    using namespace::std;
    typedef unsigned long counter;
    typedef long long element;
    
    inline void rotate (element term[], counter count, counter jump)
    {
      element temp;
      counter gcd = count, k = jump, i, position;
      for (; k != 0; i = k, k = gcd % k, gcd = i);
      for (i = 0; i != gcd; ++i)
      {
        temp = term [i];
        position = k = i;
        do
        {
          term [position] = term[k];
          position = k;
          k -= jump;
          if (k < 0) k += count;
        }
        while (k != i);
        term[position] = temp;
      }
    }
    
    counter mergesort (element term[], counter count)
    {
      if (count < 2) return 0;
      counter mid = count/2, inversions = mergesort (term, mid);
      inversions += mergesort (term + mid, count - mid);
      counter range, bound;
      element * ptr = NULL;
      for (counter left = 0, right = mid, movecount = 0; 
           right != count; right += movecount)
      {
        for (left += movecount; 
    	 left != right && term[left] <= term[right]; ++left);
        if ((range = right - left) == 0) break;
        for (ptr = term + right, movecount = 1, bound = count - right; 
    	 movecount != bound && ptr[movecount] < term[left]; ++movecount);
        rotate (term + left, range + movecount, movecount);
        inversions += movecount * range;
      }
      return inversions;
    }
    
     
    • Ankit Malhotra

      As we are using unsigned for counter which is generally what size_type returns the following replacements need to be done.

       
            k -= jump;
            if (k < 0) k += count;
       

      should be

       
            k += jump;
            if (k >= count) k -= count;
       
       
      rotate (term + left, range + movecount, movecount); 

      should be

       
      rotate (term + left, range + movecount, range); 
  • Arun

    You need to change

    inv_count += mid – i to
    inv_count += (mid-left+1-i);

    else, the result coming is not correct.

    Thanks,

    • GeeksforGeeks

      @Arun: Please take a closer look at the code. The value of mid is (left + right)/2. Let us know if you find any case for which the given code doesn’t produce the correct result.

    • bartender

      We are passing mid+1 into merge routine,so everything works out.Read my other comment for additional details.

  • Ankit Malhotra

    Simplified the code to a single merge sort function which returns the inversions. This implementation is in place and reduces looping when consecutive elements on the right side need me be moved for a single element on the left.

     
    using namespace::std;
    typedef unsigned long counter;
    typedef long long element;
    counter mergesort (element term[], counter count)
    {
      if (count < 2) return 0;
      counter mid = count/2,
      inversions = mergesort (term, mid);
      inversions += mergesort (term + mid, count - mid);
      counter prefix = 0, suffix = mid, range, movecount, bound, j;
      element * ptr = NULL;
      while (true)
      {
        for (; prefix != suffix && term[prefix] <= term[suffix]; prefix++);
        range = suffix - prefix;
        if (!range) break;
        for (ptr = term + suffix, movecount = 1, bound = count - suffix; 
    	 movecount != bound && ptr[movecount] < term[prefix]; movecount++);
        for (ptr = new (element[range]), j = 0; j < range; 
    	 ptr[j++] = term [prefix + j]);
        for (j = 0; j < movecount; term[prefix + j++] = term[suffix + j]);
        for (j = 0; j < range; term[prefix + movecount + j++] = ptr[j]);
        delete ptr;
        inversions += movecount * range;
        suffix += movecount;
        if (suffix == count) break;
      }
      return inversions;
    }
     
    • Ankit Malhotra

      delete ptr should be replaced with delete []ptr

    • Ankit Malhotra

      if (suffix == count) break;
      should also have else statement as follows
      else prefix += movecount;

  • http://friendmaybe.com pankaj

    balanced BST

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
  • hi

    This problem can also be solved using BIT and Segment Tree

    • abzx12@gmail.com

      Can you suggest the way we can use BIT to solve it?

       
      /* Paste your code here (You may delete these lines if not writing code) */
       
      • Rahul

        There you go

        #include
        #include
        #include

        using namespace std;

        typedef long long llong;

        const int MAXN = 500020;
        llong tree[MAXN], A[MAXN], B[MAXN];

        llong read(int idx){
        llong sum = 0;
        while (idx > 0){
        sum += tree[idx];
        idx -= (idx & -idx);
        }
        return sum;
        }

        void update(int idx ,llong val){
        while (idx <= MAXN){
        tree[idx] += val;
        idx += (idx & -idx);
        }
        }

        int main(int argc, char *argv[]) {
        int N;
        while(1 == scanf("%d",&N)) {
        if(!N) break;
        memset(tree, 0, sizeof(tree));
        for(int i = 0; i < N; ++i) {
        scanf("%lld",&A[i]);
        B[i] = A[i];
        }
        sort(B, B + N);
        for(int i = 0; i = 0; –i) {
        llong x = read(A[i] – 1);
        inv_count += x;
        update(A[i], 1);
        }
        printf(“%lld\n”,inv_count);
        }
        return 0;
        }

  • Venkatesh

    If we use modified insertion sort alg, we see best running time. for partially sorted array insertion sort runs in linear time.

    int arr[], array_size, inv_count;

    for (int i = 0; i 0; j–)
    if (a[j] < a[j-1]))
    inv_count ++;
    else
    break;

  • jordi

    theres a linear solution that im looking for..

    • Algoseekar

      @jordi..i dont think we can do it linearly..??

  • amit

    nice question !

  • Naman Goel

    We can also use binary search tree method for this
    here is the code-

     
    
    #include<iostream>
    using namespace std;
    
    struct node{
    	int data;
    	node *left;
    	node *right;
    	int rc;
    };
    
    node *root = NULL;
    
    int get_inv(int val)
    {
    	node *newnode = new node;
    	newnode -> data = val;
    	newnode -> left = NULL;
    	newnode -> right = NULL;
    	newnode -> rc = 0;
    	
    	int inv = 0;
    	
    	if(!root)
    	{
    		root = newnode;
    		return 0;
    	}
    	
    	node *ptr = root;
    	node *pptr = root;
    	while(ptr)
    	{
    		pptr = ptr;
    		if(val < ptr->data)
    		{
    			inv += ptr->rc +1;
    			ptr = ptr->left;
    		}
    		else
    		{
    			ptr->rc++;
    			ptr = ptr->right;
    		}
    	}
    	
    	if(val < pptr->data)
    	{
    		pptr->left = newnode;
    	}
    	else
    	{
    		pptr->right = newnode;
    	}
    	
    	return inv;
    }
    
    int count_inv(int *array,int n)
    {
    	int inv = 0;
    	for(int i=0;i<n;i++)
    	{
    		inv += get_inv(array[i]);
    	}
    	return inv; 
    }
    
    int main()
    {
    	int array[] = {3,6,1,2,4,5};
    	cout<<count_inv(array,6)<<endl;
    	return 0;
    }
     
    • J

      Really cool coding. I must learn to code like this.

    • J

      Memory is leaked in the above program. You cannot just call new and leave it alone.

    • laxman

      @nama goel ..hi naman can you explain the algorithm..its awesome program. please write the algo.

      Thanks
      laxman

    • http://www.linkedin.com/in/ramanawithu Venki

      If I understand the logic correctly, we are constructing BST from the array elements and maintaining a count on each node. The idea here is every parent node must maintain the number of nodes that branched on to it’s right side (right count). The above code fails if there are equal element which cause the count to be incremented. Equal nodes won’t participate in inversions. The count (rc) will be used to track the number of inversions.

      However, when the array is reverse sorted, the tree will be fully right skewed. While inserting i-th node, we need to visit previous (i-1) nodes, so the worst case complexity is no better than O(n^2).

      Where as merge sort procedure doesn’t depend on data to be sorted. What ever may be the permutation of input data, merge sort will sort the array in O(NlogN) time, so the inversion count.

      Let me know if I am missing something to understand.

      • Decoder

        What if we insert equal element to right child of equal element, In this case count won’t be incremented.

         
        /* Paste your code here (You may delete these lines if not writing code) */
         
      • Decoder

        What if we insert equal element to right child of equal element, In this case count won’t be incremented.

      • Apoorv

        True…worst case complexity looks like O(n*n). But this can be improved using a self balancing binary search tree like a Red Black tree.

      • Aashish

        @venki,
        I have modified the code to handle the case of duplicate items. To avoid the worst time complexity of O(N^2), self balancing BST can be used.
        Here is the code:

         
        #include <stdio.h>
        #include <stdlib.h>
         
        struct node
        {
                int data;
                int freq;
                struct node *left,*right;
        };
         
        struct node* getNode(int data)
        {
                struct node* temp=(struct node*)malloc(sizeof(struct node));
                temp->left=temp->right=NULL;
                temp->data=data;
                temp->freq=1;
                return temp;
        }
         
        int insert(struct node**root,int data)
        {
                if(!*root)
                {
                        *root=getNode(data);
                        return 0;
                }
                else if(data<(*root)->data)
                        return (*root)->freq + insert(&((*root)->left),data);
                else if(data>=(*root)->data)
                {
                        ++((*root)->freq);
                        return insert(&((*root)->right),data);
                }
        }
         
        void cal(int *arr,int size)
        {
                struct node *root=NULL;
                int i,count=0;
                for(i=0;i<size;i++)
                {
                        count+=insert(&root,arr[i]);
                }
                printf("%d ",count);
        }
         
        int main()
        {
                int arr[]={2, 4, 1, 3, 5},size;
                size=sizeof(arr)/sizeof(arr[0]);
                cal(arr,size);
                return 0;
        }
         

        Output: http://ideone.com/c2gXM

        Let me know if i am missing anything.

        • Aashish

          A little change, When the value to be inserted already exists, do not insert it in BST.

        • mrn

          I think , we can’t balance the tree. coz if we do , then e.g. in RR rotation , left subtree no more represents smaller nos. inserted after the new root.
          Please correct me if i am wrong.