标签:
题目:给出一个确定在n个不同元素的任何排列中逆序对数量的算法,最坏情况需要Θ(nlgn)时间。(提示:修改归并排序。)
思路:修改从大到小排序的归并排序。
归并排序分为三步:分解、解决、合并。
分解:将排列A分解为A1、A2两个子排列。
解决:递归的从大到小排列A1和A2,在此同样递归的求解A1、A2的逆序对数量。
合并:按照递归排序的合并策略从大到小比较A1中的元素[a1,a2,a3…]和A2中的元素[b1,b2,b3…]。
1.若a1大于b1,则a1大于A2中的所有元素,逆序对的数量加上length(A2),将a1从A1中移至输出排列,a2继续与b1比较。
2.若a1小于b1,则b1大于A1中的所有元素,b1不能与A1中的元素构成逆序对,将b1从A2中移至输出排列,b2继续与a1比较。
3.直到A1或A2中没有元素,将剩余元素移至输出排列。
合并后的逆序对的数目为合并前A1和A2中逆序对的数目之和加上合并过程中加上的逆序对数。
#include<iostream> using namespace std; int A[100]; int temp1[100]; int temp2[100]; int merge(int low1,int high1,int low2,int high2){//合并步 int inver_num=0;//合并中新增的逆序对数目。 int A_pos=low1; int size1=0;//首先将两个待合并数组复制到临时数组temp1和temp2中。 while(low1<=high1){ temp1[size1++]=A[low1++]; } int size2=0; while(low2<=high2){ temp2[size2++]=A[low2++]; } int i=0,j=0; while(size1!=0&&size2!=0){//开始合并 if(temp1[i]>temp2[j]){ A[A_pos++]=temp1[i++]; inver_num+=size2;//逆序对数目增加。 size1-=1; } else{//temp1[i]<temp2[j],没有相同元素。 A[A_pos++]=temp2[j++]; size2-=1; } } while(size2!=0){//将剩余的元素复制到输出数组。 A[A_pos++]=temp2[j++]; size2-=1; } while(size1!=0){//和上面的while只会执行一个。 A[A_pos++]=temp1[i++]; size1-=1; } return inver_num; } int inversion(int low,int high){ if(low>=high) return 0; int mid=(low+high)/2; int left_num=inversion(low,mid); int right_num=inversion(mid+1,high); int merge_num=merge(low,mid,mid+1,high); return left_num+right_num+merge_num; }
标签:
原文地址:http://www.cnblogs.com/StartoverX/p/4283186.html