您的位置:首页 > 其它

逆序对的求解

2015-07-31 15:38 183 查看
<span style="font-size:18px;">题外话:</span>
<span style="font-size:18px;"><span style="white-space:pre">	</span>看了许多文章,觉得算法对于程序员还是很重要的,不管是以后是C/C++方向程序员还是Java程序员都一样,所以今天决定重新拾起算法。做算法还是用C++来写比较方便,最近都在搞Java ,已经一个学期没碰C++,写起来还真是痛苦。</span>
<span style="font-size:18px;">正题:</span>
<span style="font-size:18px;"><span style="white-space:pre">	</span>逆序对的概念:数组s[0...N]中如果i<j ,s[i]>j就表示有一个逆序对问题:对任意一个数组求其逆序对。</span>
<span style="font-size:18px;"><span style="white-space:pre">	</span>朴素的算法当然是暴力求解了,两个for循环进行判断,时间复杂度为n的平方。</span>
<span style="font-size:18px;"><span style="white-space:pre">	</span>这里重点讲利用分治策略求解:将一个数组分为两个子数组,分别求解子数组的逆序数,在加上两个数组比较后的逆序数,于是可递归求解递归式:<strong>t(q,r)=t(q,p)+t(p+1,r)+s</strong>;若两个是子数组L,R都是有序的情况下 if(L[i]>R[j]),则从L[i]~L[end]>R[j]都成立,于是有逆序数:<strong>s=end-i</strong>;一开始我的疑问时两个子数组的排序不会对逆序数造成影响吗?经过分析,L数组的元素不论位置如何,对于R数组的元素形成的逆序对是不变的,即逆序对中<a,b>中,a来自L,b来自R。好了,现在问题快解决了,我们要求分为两个有序子数组,能用到的排序方法是归并排序了,将逆序数的统计加入到归并排序中,所以算法最终的时间复杂度是nlogn,空间复杂度是n。</span>
</pre><pre name="code" class="cpp">/*求一个数组中逆序对个数时间:2015-07-31*/#include<iostream>using namespace std;int  count=0;//治//完成两个数组的归并void f1(int *a,int q,int p,int r){int n1=p-q+1;	//两个数组长度int n2=r-p;int *L=new int(n1);int *R=new int(n2);int i=0,j=0;for(i=0;i<n1;i++)L[i]=a[q+i];for(j=0;j<n2;j++)R[j]=a[p+1+j];i=0;j=0;int k=q;while( i<n1 && j<n2 ){if(L[i]<=R[j]){a[k++]=L[i++];}else{count+=n1-i;a[k++]=R[j++];}}while(i<n1)a[k++]=L[i++];while(j<n2)a[k++]=R[j++];}//分void f2(int *a,int q,int r){if(q>=r) return ;int p=(r+q)/2;f2(a,q,p);f2(a,p+1,r);f1(a,q,p,r);}void main(){int arry[5]={5,3,4,2,1};f2(arry,0,4);printf("%d\n",count);for(int i=0;i<5;i++){printf("  %d  ",arry[i]);}}
参考博客:http://blog.csdn.net/skywalkervvv/article/details/8546702。感谢博主,侵联删。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: