归并排序(逆序对的解决)
来源:互联网 发布:手机借款软件排行 编辑:程序博客网 时间:2024/06/04 23:25
逆序对最典型的方法就是树状数组,但是还有一种方法就是归并排序:
实际上归并排序的交换次数就是这个数组的逆序对个数,为什么呢?
归并排序是将数列a[l,h]分成两半a[l,mid]和a[mid+1,h]分别进行归并排序,然后再将这两半合并起来。
在合并的过程中(设l<=i<=mid,mid+1<=j<=h),当a[i]<=a[j]时,并不产生逆序数;当a[i]>a[j]时,在
前半部分中比a[i]大的数都比a[j]大,将a[j]放在a[i]前面的话,逆序数要加上mid+1-i。因此,可以在归并
排序中的合并过程中计算逆序数:题:给定一个序列a[],每次只允许交换相邻两个数,最少要交换多少次才能把它变成非递降序列
/*归并排序 &计算逆序对 */ #include <iostream> #include <string.h> #include <stdio.h> using namespace std; const int N = 1005; int a[N],tmp[N]; //全局变量定义数组(两数组相互间变换,省去引入其他数组)int ans; //记录逆序对个数=交换次数 void Merge(int l,int m,int r) { int i = l; int j = m + 1; int k = l; while(i <= m && j <= r) { if(a[i] > a[j]) { tmp[k++] = a[j++]; ans += m - i + 1; //将a[j]放在a[i]前面,逆序数要加上mid+1-i } else { tmp[k++] = a[i++]; } } while(i <= m) tmp[k++] = a[i++]; while(j <= r) tmp[k++] = a[j++]; for(int i=l;i<=r;i++) //将临时数组转换为原数组a. a[i] = tmp[i]; } void Merge_sort(int l,int r) { if(l < r) { int m = (l + r) /2; Merge_sort(l,m); //前段排序 Merge_sort(m+1,r); //后段排序 Merge(l,m,r); //前后段对比大小排序 } } int main() { int n; scanf("%d",&n); //输入组数据 for(int i=0;i<n;i++){ scanf("%d",&a[i]); } ans = 0; Merge_sort(0,n-1); for(int i=0;i<n;i++) printf("%d",a[i]); //printf("逆序对个数为:%d"\n,ans); return 0; }
阅读全文
0 0
- 归并排序(逆序对的解决)
- 逆序对 (归并排序)
- 逆序对 归并排序
- 归并排序 & 逆序对
- 归并排序--逆序对
- 归并排序与逆序对的个数
- 归并排序--逆序数对的计算
- 归并排序-逆序对的求解
- 逆序对的求法 归并排序
- 归并排序之数组的逆序对
- 归并排序求逆序对的个数
- 逆序对/归并排序的应用
- 笔记1--逆序对(归并排序)
- POJ 2299 逆序对(归并排序)
- 数组中的逆序对(归并排序)
- 求逆序数对(归并排序)
- 求逆序对(归并排序)
- 应用归并排序解决——求逆序对问题
- HBase之——单节点安装
- [构造]AGC005C
- C# 禁用Alt+F4 的小段
- 快速入门编程,可以试试这个方法!
- java高并发程序设计总结三:JDK并发包之ReentrantLock重入锁
- 归并排序(逆序对的解决)
- VMware 黑屏解决方法
- cocos2d-x--使用doxygen+graphviz生成源码文档
- windows 环境下c++系统栈大小调整
- 素数
- HTML5 ul li 去前面的圆点 和 横排
- NGINX基于Cookie和Header的负载均衡会话保持
- Spring中标签属性name和id的区别
- 确定整数是否是回文?空间O(1)时间复杂度O(logn)