inversion指的是在一个序列a[]中若有i<j, 且a[i]>a[j],则称(i,j)为一个inversion,现要求在o(nlogn)时间内求解任一序列的inversion的总数。
如此将meger_sort改造一下,注意在meger排序中每一次数据的位置调换都对应了一个inversion,如此,o(nlogn) 时间内求任意序列的inversion的代码如下
#include <iostream>
#include <cstdlib>
#include <limits>
using namespace std;
/*
* name : merge inversion
* author : sangoly
* O(nlgn)
* S(n)
* date : 2014/4/15
*/
int merge_inversion(int a[], int start, int middle, int end)
{
int inversions = 0;
bool counted = false;
int max = numeric_limits<int>::max();
int tempArray1[middle-start+2];//include the start to middle
int tempArray2[end-middle+1];//include the middle+1 to end
for (int i=0; i<middle-start+1; i++)
tempArray1[i] = a[start+i];
tempArray1[middle-start+1] = max;//As the soldier
for (int i=0; i<end-middle; i++)
tempArray2[i] = a[middle+1+i];
tempArray2[end-middle] = max;//As the soldier
int index1 = 0;
int index2 = 0;
for (int k = start; k <= end; k++) {
if (counted == false && tempArray2[index2] < tempArray1[index1]) {
inversions += (middle - start - index1 + 1);//if the first element in tempArray1 is bigger than the j value in tempArray2
//then all the value follow index i will bigger than the j in tempArray2 too
counted = true;
}
if (tempArray1[index1] <= tempArray2[index2]) {
a[k] = tempArray1[index1++];
}
else {
a[k] = tempArray2[index2++];
counted = false;
}
}
return inversions;
}
int count_inversion(int a[], int start, int end)
{
int inversions = 0;
if (start < end) {
int middle = (start + end) / 2;
inversions += count_inversion(a, start, middle);
inversions += count_inversion(a, middle + 1, end);
inversions += merge_inversion(a, start, middle, end);
}
return inversions;
}
int main(int argc, const char **argv) {
int a[] = {2, 3, 8, 6, 1};
int total_inversions = count_inversion(a, 0, 4);
for (int i=0; i<5; i++)
cout<<a[i]<<" ";
cout<<endl;
cout << "total_inversions : " << total_inversions << endl;
system("pause");
return 0;
}