题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如,有一个数组为Array[0..n] 其中有元素a[i],a[j].如果 当i<j时,a[i]>a[j],那么我们就称(a[i],a[j])为一个逆序对。在数组{7,5,6,4}中一共存在5对逆序对,分别是(7,6),(7,5),(7,4),(6,4),(5,4)。
跟归并排序差不多,求逆序对的过程就是一个求归并排序的过程,在求出逆序对以后,原数组变得有序,是通过归并排序得到的。
(1)总体的意思就是将数组分成两段,首先求段内的逆序对数量,比如下面两段代码就是求左右两端数组段内的逆序对数量
inversions+=InversePairsCore(arry,start,mid,temp);//找左半段的逆序对数目 inversions+=InversePairsCore(arry,mid+1,end,temp);//找右半段的逆序对数目
(2)然后求段间的逆序对数量,如下面的代码
inversions+=MergeArray(arry,start,mid,end,temp);//在找完左右半段逆序对以后两段数组有序,然后找两段之间的逆序对。最小的逆序段只有一个元素。
(3)然后在求段间逆序对的时候,我们分为arry[start...mid]和arry[mid+1...end],然后设置两个指针ij分别指向两段数组的末尾元素,也就是i=mid,j=end。然后比较arry[i]和arry[j],
- 如果arry[i]>arry[j],因为两段数组都是有序的,所以arry[i]>arry[mid+1...j],这些都是逆序对,我们统计出的逆序对为j-(mid+1)+1=j-mid。并且将大数arry[i]放入临时数组temp[]当中,i往前移动
- 如果arry[i]<arry[j],则将大数arry[j]放入temp[]中,j往前移
#include<iostream>
using namespace std;
int InversePairsCore(int *data,int *copy,int start,int end)
{
if(start == end)
{
copy[start] = data[start];
return 0;
}
int length = (end-start)/2;
int left = InversePairsCore(copy,data,start,start+length); //注意此处是copy,data
int right = InversePairsCore(copy,data,start+length+1,end);
int i=start+length;
int j=end;
int indexCopy=end;
int count=0;
while(i>=start && j>=start+length+1)
{
if(data[i]>data[j])
{
copy[indexCopy--] = data[i--];
count += j-(start+length);
}
else
copy[indexCopy--] = data[j--];
}
while(i>=start)
copy[indexCopy--] = data[i--];
while(j>=start+length+1)
copy[indexCopy--] = data[j--];
return left + right + count;
}
int InversePairs(int *data,int length)
{
if(data==NULL || length<0)
return 0;
int *copy = new int[length];
for(int i=0;i<length;i++)
copy[i]=data[i];
int count = InversePairsCore(data,copy,0,length-1);
delete []copy;
return count;
}
// ====================测试代码====================
void Test(char* testName, int* data, int length, int expected)
{
if(testName != NULL)
printf("%s begins: ", testName);
if(InversePairs(data, length) == expected)
printf("Passed.\n");
else
printf("Failed.\n");
}
void Test1()
{
int data[] = { 7, 5,6,4};
int expected = 5;
Test("Test1", data, sizeof(data) / sizeof(int), expected);
}
// 递减排序数组
void Test2()
{
int data[] = {6, 5, 4, 3, 2, 1};
int expected = 15;
Test("Test2", data, sizeof(data) / sizeof(int), expected);
}
// 递增排序数组
void Test3()
{
int data[] = {1, 2, 3, 4, 5, 6};
int expected = 0;
Test("Test3", data, sizeof(data) / sizeof(int), expected);
}
// 数组中只有一个数字
void Test4()
{
int data[] = {1};
int expected = 0;
Test("Test4", data, sizeof(data) / sizeof(int), expected);
}
// 数组中只有两个数字,递增排序
void Test5()
{
int data[] = {1, 2};
int expected = 0;
Test("Test5", data, sizeof(data) / sizeof(int), expected);
}
// 数组中只有两个数字,递减排序
void Test6()
{
int data[] = {2, 1};
int expected = 1;
Test("Test6", data, sizeof(data) / sizeof(int), expected);
}
// 数组中有相等的数字
void Test7()
{
int data[] = {1, 2, 1, 2, 1};
int expected = 3;
Test("Test7", data, sizeof(data) / sizeof(int), expected);
}
void Test8()
{
int expected = 0;
Test("Test8", NULL, 0, expected);
}
int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
Test8();
return 0;
}