逆序对(inversion pair)是指在序列{a0,a1,a2...an}中,若ai<aj(i>j),则(ai,aj)上一对逆序对。而逆序数 (inversion number)顾名思义就是序列中逆序对的个数。例如: 1 2 3是顺序,则逆序数是0;1 3 2中(2,3)满足逆序对的条件,所以逆序数只有1; 3 2 1中(1,2)(1,3)(2,3)满足逆序对,所以逆序是3。由定义不难想象,序列n的逆序数范围在[0,n*(n-1)/2],其中顺序时逆序数为 0,完全逆序时逆序数是n*(n-1)/2。
就我所知,目前求这种逆序对最快的算法是利用归并排序,其时间复杂度为O(nlgn), 空间复杂度为O(n)。
代码如下:view plaincopy to clipboardprint?
#include <iostream>
#include <cstring>
using namespace std;
long c[500005];
long a[500005];
long b[500005];
long long num=0;
const long MAX=1000000000;
void merge(int s,int p,int e)
{
memcpy(a,c+s,sizeof(long)*(p-s+1));
memcpy(b,c+p+1,sizeof(long)*(e-p));
int l1 = p-s+1;
int l2 = e-p;
a[l1] = b[l2] = MAX;//在比较过程中设置尾部哨兵
int i =0;
int j = 0;
int k =0;
/*
while(i<l1 && j<l2)
{
if(a[i]<b[j])
{
c[k++] = a[i];
i++;
}
else if(a[i]>b[j])
{
c[k++]=b[j];
j++;
}
else
{
c[k++]=a[i];
i++;
j++;
}
}
*/
//a[i]表示前半部分
//b[i]表示后半部分
//逆序数的表现位:
//i<j && v[i]>v[j]
for(k=s;k<=e;k++)
{
if(a[i]<=b[j])
{
c[k]=a[i];
i++;
}
else
{
c[k]=b[j];
j++;
num+=l1-i;
/*
此时就表现出了逆序数的特征,因为a[i]>b[j],并且a和b中数据都有序,所以a[i+1,...,l1]>b[j],故num增加l1-i。
比如a={4,7,9,MAX}
b={5,6,8,MAX}
当i=1时,a[i]=7,此时a[i]>b[j]=5,并且a[i+1]=9>b[j],此时num增加l1-i=2;
*/
}
}
}
void merge_sort(int s,int e)
{
if(s<e)
{
int p = (e+s)/2;
merge_sort(s,p);
merge_sort(p+1,e);
merge(s,p,e);
}
}
int main()
{
int n ;
int i = 0;
cin>>n;
while(n!=0)
{
i = 0;
memset(a,0,sizeof(0));
memset(b,0,sizeof(0));
memset(c,0,sizeof(0));
num=0;
for(i=0;i<n;i++)
cin>>c[i];
merge_sort(0,n-1);
cout<<num<<endl;
cin>>n;
}
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/clearriver/archive/2009/05/10/4165642.aspx