题目描述:
根据维基百科的定义:
插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。
归并排序进行如下迭代操作:首先将原始序列看成 N 个只包含 1 个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下 1 个有序的序列。
现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?
输入格式:
输入在第一行给出正整数 N (≤100);随后一行给出原始序列的 N 个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。
输入样例:
输出格式:
首先在第 1 行中输出Insertion Sort表示插入排序、或Merge Sort表示归并排序;然后在第 2 行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行首尾不得有多余空格。
输出样例:
分析:这道题按照我的思路,最后一个样例点怎么也过不了,原因是处理是归并排序的代码有点小问题(下面再说),最后只能参考柳神处理归并排序的代码才解决。
首先思路就是根据两种排序的特点来判断是哪种排序算法,插入排序是将当前待排元素插入到前面的有序序列中成为一个新的有序序列。首先遍历第二个输入序列,得到其中有序序列后面第一个元素的索引,如果该索引位置到最后一个位置的序列和第一个输入序列的相应部分相同(待排的无序序列),则说明是插入排序,接着用sort函数将这个索引的元素插入到前面有序序列即可。不满足条件就是归并排序了,柳神处理归并排序那段代码是对第一个输入序列进行归并排序,如果到某一次排序时,序列与第二个输入序列相同了,则再进行一次排序就得到输出了。
我的错误思路:得到有序序列后面第一个元素的索引,设为t,那么前面有序序列就是t个元素了,所以我认为这一次归并排序每组待排元素个数就是t,那么下次归并排序每组元素个数就是t*2,接着每t个元素序列用sort排序即可。
错误原因:比如下面的输入:
首先这是归并排序。第二个输入序列的有序序列后面第一个元素索引为3,按照我的思路这次归并排序每组元素个数就是3个,实际上这次归并排序每组元素个数为2个。
所以我有一个样本点过不了的原因就是:有序序列后面第一个元素的索引t不一定就是当前归并排序每组元素的个数。
正确代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n, i;
cin>>n;
int arr[n];
for(i = 0; i < n; i++)
cin>>arr[i];
int arr1[n];
for(i = 0; i < n; i++)
cin>>arr1[i];
int t = 0;
i = 1;
while(i < n && arr1[i-1] <= arr1[i]) i++; //z这里不加等于号会报浮点错误
t = i;
for(i = t; i < n; i++){
if(arr[i] != arr1[i])
break;
}
if(i == n){
cout<<"Insertion Sort"<<endl;
sort(arr,arr+t+1);
}else {
cout << "Merge Sort" << endl;
int k = 1, flag = 1;
while(flag) {
flag = 0;
for (i = 0; i < n; i++) {
if (arr[i] != arr1[i])
flag = 1;
}
k = k * 2;
for (i = 0; i < n / k; i++)
sort(arr + i * k, arr + (i + 1) * k);
sort(arr + i * k, arr + n);
}
}
for(i = 0; i < n; i++){
cout<<arr[i];
if(i != n-1)
cout<<" ";
}
return 0;
}