根据维基百科的定义:
插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。
归并排序进行如下迭代操作:首先将原始序列看成N个只包含1个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下1个有序的序列。
现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?
输入格式:
输入在第一行给出正整数N (<=100);随后一行给出原始序列的N个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。
输出格式:
首先在第1行中输出“Insertion Sort”表示插入排序、或“Merge Sort”表示归并排序;然后在第2行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行末不得有多余空格。
输入样例1:
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
输出样例1:
Insertion Sort
1 2 3 5 7 8 9 4 6 0
输入样例2:
10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6
输出样例2:
Merge Sort
1 2 3 8 4 5 7 9 0 6
分析:先将i指向中间序列中满足从左到右是从小到大顺序的最后一个下标,再将j指向从i+1开始,第一个不满足a[j] == b[j]的下标,如果j顺利到达了下标n,说明是插入排序,再下一次的序列是sort(a, a+i+2);否则说明是归并排序。归并排序就别考虑中间序列了,直接对原来的序列进行模拟归并时候的归并过程,i从0到n/k,每次一段段得sort(a + i * k, a + (i + 1) * k);最后别忘记还有最后剩余部分的sort(a + n / k * k, a + n);这样是一次归并的过程。直到有一次发现a的顺序和b的顺序相同,则再归并一次,然后退出循环~
注意:一开始第三个测试点一直不过,天真的我以为可以模拟一遍归并的过程然后在过程中判断下一步是什么。。然而真正的归并算法它是一个递归过程。。也就是先排左边一半,把左边的完全排列成正确的顺序之后,再排右边一半的。。而不是左右两边一起排列的。。后来改了自己的归并部分判断的代码就过了。。。。◕‿◕。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include <iostream> #include <algorithm> using namespace std; int main() { int n, a[100], b[100], i, j; cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i < n; i++) cin >> b[i]; for (i = 0; i < n - 1 && b[i] <= b[i + 1]; i++); for (j = i + 1; a[j] == b[j] && j < n; j++); if (j == n) { cout << "Insertion Sort" << endl; sort(a, a + i + 2); } else { cout << "Merge Sort" << endl; int k = 1, flag = 1; while(flag) { flag = 0; for (i = 0; i < n; i++) { if (a[i] != b[i]) flag = 1; } k = k * 2; for (i = 0; i < n / k; i++) sort(a + i * k, a + (i + 1) * k); sort(a + n / k * k, a + n); } } for (j = 0; j < n; j++) { if (j != 0) printf(" "); printf("%d", a[j]); } return 0; } |