利用归并排序求有限序列的逆序数
2013-12-08 23:24
274 查看
利用归并排序求有限序列的逆序数
逆序数对:在一个序列A={a1, a2, … , an}中,满足i<j, ai>aj的一对元素称为一个逆序数对。那么,怎么求出一个序列的逆序数对的个数呢?
最简单的方法就是顺序扫描序列,求出每个元素的逆序数对,累加即可,时间复杂度是O(n2)。下面我介绍一种时间复杂度是O(nlgn)(注:lgn=log2n)的算法,它由归并排序修改而来。
在归并排序的合并过程中,左半部分元素的位置在原序列中的位置总是小于右半部分的元素,而且各个元素的相对位置在合并之前不会改变,因此利用合并的过程就可以计算出逆序数对的个数。具体做法如下,当左半部分的某个元素ai被合并时,那么右半部分中与ai比较的那个元素设为bj,则右半部分bj之前的那些元素肯定比ai小,因此形成j个逆序数对,因此总逆序数对累加j,当归并排序完成时,即可得出结果。
程序如下:
#include <iostream> using namespace std; //合并有序序列A[p,...,q]和A[q+1,...,r],求取A[p,...,r]区间内的逆序数 int update(int *A, int p, int q, int r) { int *merge = new int[r-p+1]; if (!merge) return 0; int i=p, j=q+1, k=0, c=0; while(i<=q && j<=r) { if(A[i] <= A[j]) { merge[k++] = A[i++]; c += j-q-1; //A[i]大于A[q+1,...,j-1],因此c增加j-q-1 } else { merge[k++] = A[j++]; } } while(i<=q)//左半部分的元素没有合并完,则继续更新c { merge[k++] = A[i++]; c += j-q-1; //A[i]大于A[q+1,...,j-1],因此c增加j-q-1 } while(j<=r) merge[k++] = A[j++]; k=0; while(p<=r) { A[p++] = merge[k++]; } delete []merge; return c; } //求A中p~r区间里逆序数对的个数,用参数c返回结果 int nixushu(int *A, int p, int r) { int count = 0; if(p < r) { int q = (p+r)/2; count += nixushu(A, p, q); count += nixushu(A, q+1, r); count += update(A, p, q, r); } return count; } int nixushu(const int *A, int n) { int *copyA = new int ; if (!copyA) return 0; for (int i=0; i<n; i++) copyA[i] = A[i]; int count = nixushu(copyA, 0, n-1); delete []copyA; return count; } int main() { int A1[] = {0, 1, 2, 3, 4, 5, 6}; int A2[] = {6, 5, 4, 3, 2, 1, 0}; int A3[] = {4, 5, 2, 5, 6, 1, 7, 1}; int c1 = nixushu(A1, 7); int c2 = nixushu(A2, 7); int c3 = nixushu(A3, 8); cout <<"A1的逆序数:" << c1 << endl; cout <<"A2的逆序数:" << c2 << endl; cout <<"A3的逆序数:" << c3 << endl; return 0; }
相关文章推荐
- codeforces 371B - Fox Dividing Cheese
- codeforces 371B - Fox Dividing Cheese
- 使用google 两步验证的一个库
- disable_preempt
- [研究探讨]Mysql 集群(图)
- Winform开发框架之客户关系管理系统(CRM)的报价单和销售单的处理
- codechef Prime Distance On Tree(树分治+FFT)
- Java 容器的使用
- 2013年12月8日 周记
- poj 2718
- 树洞
- 鬼脚七:走出来,正视自己 新闻来源:( i天下网商)
- 指针函数的作用
- Android学习之常见的布局方式
- 平衡树之splay讲解
- SupremeWord 进度:14.8%
- C语言字符串操作函数
- [How to][Decompile and Recompile apks easily]{APKMULTITOOL METHOD}
- 【译】在Asp.Net中操作PDF - iTextSharp - 利用列进行排版(转)
- Windows phone Media Hub 如何清理播放历史