在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
在归并排序的一次merge中,R[j-1]<L[i],L[i-1]<=R[j]。
法一(统计i的逆序数):
int merge(int *A,int p,int q,int r) { int n1=q-p+1,n2=r-q; int *L=new int[n1+1],*R=new int[n2+1]; for(int i=0;i<n1;++i)L[i]=A[p+i]; for(int i=0;i<n2;++i)R[i]=A[q+1+i]; L[n1]=R[n2]=INT_MAX; int i=0,j=0,inversions=0; for(int k=p;k<=r;++k) { if(L[i]<=R[j]) //R[j-1]<L[i]<=R[j],i的逆序是j。 { inversions+=j; A[k]=L[i++]; } else A[k]=R[j++]; } delete [] L,R; return inversions; } int mergeSort(int *A,int p,int r) { int inversions=0; if(p<r) { int q=p+(r-p)/2; inversions+=mergeSort(A,p,q); inversions+=mergeSort(A,q+1,r); inversions+=merge(A,p,q,r); } return inversions; }
法二(统计j的逆序数):
int merge(int *A,int p,int q,int r) { int n1=q-p+1,n2=r-q; int *L=new int[n1+1],*R=new int[n2+1]; for(int i=0;i<n1;++i)L[i]=A[p+i]; for(int i=0;i<n2;++i)R[i]=A[q+1+i]; L[n1]=R[n2]=INT_MAX; int i=0,j=0,inversions=0; for(int k=p;k<=r;++k) { if(L[i]>R[j]) //L[i-1]<=R[j]<L[i],j的逆序是n1-i。 { inversions+=n1-i; A[k]=R[j++]; } else A[k]=L[i++]; } delete [] L,R; return inversions; } int mergeSort(int *A,int p,int r) { int inversions=0; if(p<r) { int q=p+(r-p)/2; inversions+=mergeSort(A,p,q); inversions+=mergeSort(A,q+1,r); inversions+=merge(A,p,q,r); } return inversions; }