PAT--1035 插入与归并

题目描述

根据维基百科的定义:

插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。

归并排序 进行如下迭代操作:首先将原始序列看成 N N N 个只包含 1 1 1 个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下 1 1 1 个有序的序列。

现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?

输入格式:

输入在第一行给出正整数 N ( ≤ 100 ) N (\leq 100) N(≤100);随后一行给出原始序列的 N N N 个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。

输出格式:

首先在第 1 1 1 行中输出 Insertion Sort 表示插入排序、或 Merge Sort 表示归并排序;然后在第 2 2 2 行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行首尾不得有多余空格。

输入样例 1:

in 复制代码
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0

输出样例 1:

out 复制代码
Insertion Sort
1 2 3 5 7 8 9 4 6 0

输入样例 2:

in 复制代码
10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6

输出样例 2:

out 复制代码
Merge Sort
1 2 3 8 4 5 7 9 0 6

解析

  • 插入排序。最前面若干个数保证有序,后续部分保持原样,因此我们就可以遍历一次,找出第一个逆序的位置,记为 p o s pos pos,那么我们就比较一下 a , b a,b a,b 数组对于 p o s , n pos,n pos,n 这个区间内是否相同,如果相同,那么就说明是插入排序。
  • 归并排序。第一次每两个一组,内部排序,第二次四个一组,内部排序,以此类推。因此我们可以枚举 2 , 4 , 8 , . . . 2,4,8,... 2,4,8,...,对 a a a 数组进行排序,直到某一次,发现排完序之后 a a a 数组和 b b b 数组相同了,假设当前每一组的元素个数为 i i i,那么我们下一步就是要将每 i ∗ 2 i*2 i∗2 个元素为一组进行排序,再排序一次即可。

代码实现

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int a[N], b[N];
void solve() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	for (int i = 1; i <= n; i++) cin >> b[i];
	int pos = -1;
	for (int i = 2; i <= n; i++) {
		if (b[i] < b[i - 1]) {
			pos = i;//找到第一个逆序的位置
			break;
		}
	}
	bool ok = true;//判断是否是插入排序
	for (int i = pos; i <= n; i++) if (a[i] != b[i]) ok = false;
	if (ok) {
		cout << "Insertion Sort\n";
		sort(a + 1, a + pos + 1);//下一步就是把[1,pos]排好序
		for (int i = 1; i <= n; i++) {
			if (i != 1) printf(" ");
			cout << a[i];
		}
	} else {
		cout << "Merge Sort\n";
		for (int i = 2; i <= n; i *= 2) {//枚举当前排序块的长度
			for (int l = 1; l <= n; l += i) sort(a + l, a + min(n, l + i - 1) + 1);
			bool ok = true;//判断是否到达题目给定的状态
			for (int k = 1; k <= n; k++) if (a[k] != b[k]) ok = false;//判断是否相同了
			if (ok) {//如果到达,直接模拟下一步即可
				i *= 2;
				for (int l = 1; l <= n; l += i) sort(a + l, a + min(n, l + i - 1) + 1);
				for (int j = 1; j <= n; j++) {
					if (j != 1) cout << " ";
					cout << a[j];
				}
				return;
			}
		}
	}
}
int main()
{
	int t = 1;
	//cin>>t;
	while (t--) solve();
	return 0;
}
相关推荐
YH55269842 小时前
GPT‑5.6 Sol 原本支持 1M 上下文,Codex 现已放开此前限制,如何看待这次调整?
java·jvm·人工智能·gpt·算法·chatgpt
遥感知识服务3 小时前
从局部阈值、双极化到暗地表剔除:NASA OPERA DSWx-S1全球动态水体算法拆解
大数据·人工智能·深度学习·神经网络·算法·机器学习
晚风醉蝶3 小时前
1-13-TimSort
算法
ZJU_统一阿萨姆4 小时前
【算子开发】算子融合与Softmax_LayerNorm实现
人工智能·算法·语言模型·硬件架构
叩码以求索5 小时前
浅谈:前序遍历反转法求解N叉树的后序遍历
算法
北风toto7 小时前
中缀、前缀、后缀表达式
算法·软件设计师
听取WA声一片(无恶意)7 小时前
CSP-J/CSP-S 深度优先搜索(DFS)完全讲义
c++·算法·深度优先
码流怪侠7 小时前
2026年8月GitHub热榜深度拆解:Agent Skills席卷开源圈,一个“技能包“收割5万星
算法·程序员·github
hold?fish:palm7 小时前
30 两两交换链表中的节点
数据结构·算法·链表
Nil2087 小时前
leetcode 98验证二叉搜索树
算法·leetcode·职场和发展