逆序数的求法
Posted 泡面小王子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逆序数的求法相关的知识,希望对你有一定的参考价值。
求一个数列的逆序数
逆序对:数列s[1],a[2],a[3]…中的任意两个数s[i],s[j] (i<j),如果s[i]>s[j],那么我们就说这两个数构成了一个逆序对
逆序数:一个数列中逆序对的总数
如数列 3 5 4 8 2 6 9
(5,4)是一个逆序对,同样还有(3,2),(5,2),(4,2)等等
那么如何求得一个数列的逆序数呢?
方法1:一个一个的数
最简单也是最容易想到的方法就是,对于数列中的每一个数s[i],遍历数列中的数s[j](其中j<i),若s[i]<s[j],则逆序数加1,这样就能统计出该数列的逆序数总和
该方法的时间复杂度为O(n2),具体过程就不细说了
代码如下:(POJ 1804 Brainman)
http://poj.org/problem?id=1804
/*直接求逆序数O(n^2)*/ //Memory Time //220K 188MS #include <iostream> using namespace std; int main(int i,int j) { int test; cin>>test; for(int p=1;p<=test;p++) { int n; cin>>n; int* s=new int[n+1]; for(i=1;i<=n;i++) cin>>s[i]; int t=0; //s[]的逆序数 for(i=1;i<=n-1;i++) //把S[i]和s[i+1~n]的元素逐个比较 for(j=i+1;j<=n;j++) if(s[i]>s[j]) //如果s[i] > s[j] (j∈[i+1,n]) t++; //则逆序数t++ cout<<"Scenario #"<<p<<‘:‘<<endl<<t<<endl<<endl; delete s; } return 0; }
方法2:归并的思想
有一种排序的方法是归并排序,归并排序的主要思想是将整个序列分成两部分,分别递归将这两部分排好序之后,再和并为一个有序的序列.复杂度为O(nlogn)算法
/*借助Mergesort求逆序数O(nlogn)*/ //Memory Time //228K 172MS #include<iostream> using namespace std; const int inf=1000001; int t; //数字序列s[]的逆序数 void compute_t(int* s,int top,int mid,int end) { int len1=mid-top+1; int len2=end-mid; int* left=new int[len1+2]; int* right=new int[len2+2]; int i,j; for(i=1;i<=len1;i++) left[i]=s[top+i-1]; left[len1+1]=inf; for(j=1;j<=len2;j++) right[j]=s[mid+j]; right[len2+1]=inf; i=j=1; for(int k=top;k<=end;k++) if(left[i]<=right[j]) s[k]=left[i++]; else { s[k]=right[j++]; t+=len1-i+1; } delete left; delete right; return; } void mergesort(int* s,int top,int end) { if(top<end) { int mid=(top+end)/2; mergesort(s,top,mid); mergesort(s,mid+1,end); compute_t(s,top,mid,end); } return; } int main(void) { int test; cin>>test; for(int p=1;p<=test;p++) { int n; //数字序列s[]长度 cin>>n; int* s=new int[n+1]; for(int i=1;i<=n;i++) cin>>s[i]; t=0; mergesort(s,1,n); cout<<"Scenario #"<<p<<‘:‘<<endl<<t<<endl<<endl; delete s; } return 0; }
以上是关于逆序数的求法的主要内容,如果未能解决你的问题,请参考以下文章