算法1:求逆序对数与显著逆序对数(归并排序)
来源:互联网 发布:white trash 知乎 编辑:程序博客网 时间:2024/06/06 05:24
写在前面:由本文开始记录本人的算法刷题之路,日后会不定期更新,欢迎讨论!本系列系本人原创,如需转载或引用,请注明原作者及文章出处。
求逆序对数问题是归并排序的基础问题,显著逆序对数则是逆序对数的升级版。POJ2299,POJ1804均是此类问题(但是个别细节不同,例如POJ2299需要将逆序对数变量num设为long long int型)。
一、求逆序对数
描述
对于一个长度为N的整数序列A,满足i < j 且 Ai > Aj的数对(i,j)称为整数序列A的一个逆序。请求出整数序列A的所有逆序对个数
输入包含多组测试数据,每组测试数据有两行
第一行为整数N(1 <= N <= 20000),当输入0时结束
第二行为N个整数,表示长为N的整数序列
第一行为整数N(1 <= N <= 20000),当输入0时结束
第二行为N个整数,表示长为N的整数序列
每组数据对应一行,输出逆序对的个数
归并排序,大家看代码自行理解吧。
代码
#include<iostream>#include<algorithm>using namespace std;int n, a[20010], temp[20010], num;void merge(int begin, int mid, int end){int i = begin;int j = mid + 1;int k = begin;while (i <= mid && j <= end){if (a[i] > a[j]){temp[k] = a[j];k++;j++;num += mid - i + 1;}else{temp[k] = a[i];k++;i++;}}while (i <= mid){temp[k] = a[i];k++;i++;}while (j <= end){temp[k] = a[j];k++;j++;}for (int p = begin; p <= end; p++)a[p] = temp[p];}void mergesort(int begin, int end){if (begin >= end)return;int mid = (begin + end) / 2;mergesort(begin, mid);mergesort(mid + 1, end);merge(begin, mid, end);}int main(){while (1){cin >> n;if (n == 0)break;for (int i = 0; i < n; i++)cin >> a[i];num = 0;mergesort(0, n - 1);cout << num << endl;}return 0;}
描述
对于一个长度为N的整数序列A,满足i < j 且 Ai > 2 * Aj的数对(i,j)称为整数序列A的一个显著逆序。请求出整数序列A的所有显著逆序对个数
输入包含多组测试数据,每组测试数据有两行
第一行为整数N(1 <= N <= 20000),当输入0时结束
第二行为N个整数,表示长为N的整数序列
第一行为整数N(1 <= N <= 20000),当输入0时结束
第二行为N个整数,表示长为N的整数序列
每组数据对应一行,输出显著逆序对的个数
解体思路
与求逆序对数不同,由于Ai > 2 * Aj,因此需要将排序和计数分别操作。也就是先做count,再做merge。
代码
#include<iostream>#include<algorithm>using namespace std;int n, a[20010], temp[20010], num;void mcount(int begin, int mid, int end){int i = begin;int j = mid + 1;int k = begin;while (i <= mid && j <= end){if (a[i] > 2 * a[j]){num += mid - i + 1;j++;}elsei++;}}void merge(int begin, int mid, int end){int i = begin;int j = mid + 1;int k = begin;while (i <= mid && j <= end){if (a[i] > a[j]){temp[k] = a[j];k++;j++;}else{temp[k] = a[i];k++;i++;}}while (i <= mid){temp[k] = a[i];k++;i++;}while (j <= end){temp[k] = a[j];k++;j++;}for (int p = begin; p <= end; p++)a[p] = temp[p];}void mergesort(int begin, int end){if (begin >= end)return;int mid = (begin + end) / 2;mergesort(begin, mid);mergesort(mid + 1, end);mcount(begin, mid, end);merge(begin, mid, end);}int main(){while (1){cin >> n;if (n == 0)break;for (int i = 0; i < n; i++)cin >> a[i];num = 0;mergesort(0, n - 1);cout << num << endl;}return 0;}
1 0
- 算法1:求逆序对数与显著逆序对数(归并排序)
- 归并排序算法求逆序对数
- 归并排序求逆序对数)
- 归并排序&求逆序对数
- 归并排序求逆序对数
- 归并排序求逆序对数
- 归并排序求逆序对数
- 求逆序对数(利用归并排序)
- 归并求逆序对数
- 归并求逆序对数
- 逆序对数(归并排序)
- 归并排序-逆序对数
- POJ 2299 归并排序 求逆序对数
- 归并排序与分治法求逆序对数
- POJ 2299 Ultra-QuickSort(归并排序求逆序对数)
- POJ 1804 Brainman (归并排序 -- 求逆序对数)
- 1:求逆序对数
- 归并排序 and 逆序对数(分治)
- Anaconda的安装与配置
- FND_MESSAGE使用
- 使用python中的matplotlib进行绘图分析数据
- 算法训练 区间k大数查询
- R语言一元线性回归
- 算法1:求逆序对数与显著逆序对数(归并排序)
- Python 多线程
- bash shell 临时笔记
- 树莓派用户管理
- 算法训练 动态数组使用
- IPython和IPython Notebook的安装和简单应用
- 主板(一)
- XML之DOM解析
- Android原生库和架构层通信的socket