0
votes

Inversion in an array a of size n is called a pair (i,j) for which it holds that i<j and a[i]>a[j]. I'm trying to implement a function in C++ which counts the number of inversions in a given array. I followed the divide and conquer approach, which just modifies the merge sort algorithm, and runs in O(n log n ) time. Here is my code so far:

long long int glob;

template< class T >
long long int merge( T *arr, int beg, int mid, int end ) {
  queue< int > left;
  queue< int > right;

  for( int i=beg; i<=mid; ++i ) {
    left.push( arr[i] );
  }
  for( int i=mid+1; i<=end; ++i ) {
    right.push( arr[i] );
  }

  int index=beg;
  int ret=0;

  while( !left.empty() && !right.empty() ) {
    if( left.front() < right.front() ) {
      arr[index++] = left.front();
      left.pop();
    } else {
      arr[index++] = right.front();
      right.pop();
      ret+=left.size();
    }
  }

  while( !left.empty() ) { arr[index++]=left.front();left.pop(); }
  while( !right.empty() ) { arr[index++]=right.front();right.pop(); }

  return ret;
}

template< class T >
void mergesortInvCount( T *arr, int beg, int end ) {
  if( beg < end ) {
    int mid = (int)((beg+end)/2);
    mergesortInvCount( arr, beg, mid );
    mergesortInvCount( arr, mid+1, end );
    glob += merge( arr, beg, mid, end );
  }
}

For some test cases it produces correct results, but for some others it gives me wrong output. Have I understood the algorithm wrongly, or I have done a mistake at the implementation? Could somebody help me? Thanks in advance.

Test case: 2 1 3 1 2
Correct: 4
Mine: 6
2
Can't you learn to use a debugger -e.g. gdb- to debug your program (you may want to compile it with g++ -Wall -g on Linux).Basile Starynkevitch
Have you though about giving us a more concrete error descriptions (like the testcases and the expected and actual (incorrect) results)?Grizzly
I don't know what algorithm you're trying to use (so e.g. I don't know what arr is supposed to contain), but the algorithm I'm familiar with use BIT trees/Fenwick trees.j_random_hacker

2 Answers

2
votes

I didn't check out all steps in your code, but your line

if( left.front() < right.front() )

suggest to me, that in the else-branch "ret" is increased not only when a(j)>a(i), but also when they are equal, which does not correspond to your description of the case. So maybe you should try to change the line quoted above into:

if( left.front() <= right.front() )

Regards

1
votes

The test

if( left.front() < right.front() )

should be <=. You're now moving identical values from the right half before the one from the left half, counting inversions that aren't (each such occurrence counts number-of-identical-items-in-left spurious inversions). In your example, you have to duplicate pairs, each creating one phantom inversion.