蒟蒻写文,难免出错,欢迎大佬来踩!
逆序对的定义
其实逆序对是一个非常简单的概念。对于一个数组中的任何一个数,只要有一个在它后面的数小于它本身,那么这两个数字就构成了一个逆序对。我们举一个例子。
对于这样一个数组
A[4]={1,4,2,3};
其中有两对逆序对,分别是(4,2)和(4,3)。
求逆序对个数的方式
有没有感觉刚才找逆序对的方法与归并排序很相似。没错,我们就使用归并排序的方法统计逆序对个数。
首先,我们要先执行分组的操作,对于数组A[0..n],我们通过归并的方式分组,最终我们能将数组成对分成n+1个小组,每组一个数据。
紧接着,我们开始两组两组地合并。但是在和并一定要注意记录,当出现前一组的待和并数据突然小于后一组待和并数据时,表明发现了逆序对。至于发现了多少个逆序对呢?应该是左侧一组的剩余数据数,这是因为我们在合并的时候左右两组已经是有序的序列了。经过统计,我们会在归并排序和并过程完成后得到逆序对个数。
那么实现上述思路的C++代码如下:
/*
import guide
int a[] shold be set as the target array
int aux[] shoule be set as the auxilary array
ALWAYS call he function distribute()
DO NOT call the function _combine() for it is not complete.
*/
void _combine(int left,int mid,int right){
int l=left,r=mid+1,aux_ptr=left;
while(l<=mid&&r<=right){
if(a[l]>a[r]){
aux[aux_ptr++]=a[r++];
ans+=mid-l+1;
}else aux[aux_ptr++]=a[l++];
}
while(l<=mid) aux[aux_ptr++]=a[l++];
while(r<=right) aux[aux_ptr++]=a[r++];
for(int i=left;i<=right;i++) a[i]=aux[i];
return;
}
void distribute(int left,int right){
if(left>=right) return;
else{
int mid=(left+right)>>1;
distribute(left,mid);
distribute(mid+1,right);
combine(left,mid,right);
return;
}
}