题目

根据维基百科的定义:

插⼊排序是迭代算法,逐⼀获得输⼊数据,逐步产⽣有序的输出序列。每步迭代中,算法从输⼊序列中取出⼀元素,将之插⼊有序序列中正确的位置。如此迭代直到全部元素有序。归并排序进⾏如下迭代操作:⾸先将原始序列看成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

题目分析

已知原始数组a,和对a排序过程中数组b,判断是归并排序还是插入排序,并打印再进行一轮排序后的结果

解题思路

判断是归并排序还是插入排序--插入排序过程中数组特点:第一个非升序数字(假设其索引为i)后的剩余数字都与原数组中相同位置数字相同

思路 01

  1. 如果是插入排序,对[0,i+1]的数字进行排序就是下一轮插入排序的结果
  2. 如果是归并排序,从原始数组使用非递归归并代码执行归并过程,并在每一轮判断排序结果是否已经是题目中已知的数组b,若是,则再进行一轮归并即可得出结果

思路 02

  1. 对原始数组分别进行插入排序和归并排序,在每一轮结束后,判断排序结果是否已经是题目中已知的数组b,若是,则再进行一轮排序即可得出结果

Code

Code 01

#include <iostream>
#include <algorithm>
using namespace std;
int main() {
// 1 接收输入
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];
// 2 判断是哪种排序
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); // 如果有右边剩余,对齐进行排序
}
}
// 3 打印数组
for (j = 0; j < n; j++) {
if (j != 0) printf(" ");
printf("%d", a[j]);
}
return 0;
}

Code 02

#include <iostream>
#include <algorithm>
using namespace std;
const int N=111;
int origin[N],tempOri[N],changed[N];
int n; //元素个数
// 判断数组是否相等
bool isSame(int A[],int B[]) {
for(int i=0; i<n; i++)
if(A[i]!=B[i])return false;
return true;
}
// 打印数组
void showArray(int A[]) {
for(int i=0; i<n; i++) {
printf("%d",A[i]);
if(i<n-1)printf(" ");
}
printf("\n");
}
// 插入排序
bool insert_sort() {
bool flag = false;
for(int i=1; i<n; i++) {
if(i!=1&&isSame(tempOri,changed)) {
flag = true;
}
// 写法一:
int j,temp = tempOri[i];
for(j=i-1; j>=0; j--) {
if(temp>=tempOri[j])break;
else tempOri[j+1]=tempOri[j];
}
tempOri[j+1]=temp;
// 写法二:
// int j=i,temp = tempOri[i];
// while(j>0&&tempOri[j-1]>temp){
// tempOri[j]=tempOri[j-1];
// j--;
// }
// tempOri[j]=temp;
if(flag)return true;
}
return false;
}
// 归并排序
void merge_sort() {
bool flag = false;
for(int step=2; step/2<=n; step*=2) { // 每次步长扩大一倍
if(step!=2&&isSame(tempOri,changed))
flag = true;
for(int i=0; i<n; i+=step) // 一轮排序,分成很多step组
sort(tempOri+i,tempOri+min(i+step,n)); //每个step组升序排序
if(flag) {
showArray(tempOri);
return;
}
}
}
int main(int argc, char * argv[]) {
scanf("%d",&n);
for(int i=0; i<n; i++) {
scanf("%d",&origin[i]);
tempOri[i]=origin[i];
}
for(int i=0; i<n; i++) {
scanf("%d",&changed[i]);
}
if(insert_sort()) {
printf("Insertion Sort\n");
showArray(tempOri);
} else {
printf("Merge Sort\n");
for(int i=0; i<n; i++) {
tempOri[i]=origin[i]; //还原tempOri数组
}
merge_sort();
}
return 0;
}

PAT Basic 插⼊与归并(25) [two pointers]的更多相关文章

  1. PAT 1035. 插入与归并(25)

    根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序. 归并排序进行如下迭 ...

  2. PAT Basic 1070 结绳 (25 分)

    给定一段一段的绳子,你需要把它们串成一条绳.每次串连的时候,是把两段绳子对折,再如下图所示套接在一起.这样得到的绳子又被当成是另一段绳子,可以再次对折去跟另一段绳子串连.每次串连后,原来两段绳子的长度 ...

  3. PAT Basic 1050 螺旋矩阵 (25 分)

    本题要求将给定的 N 个正整数按非递增的顺序,填入“螺旋矩阵”.所谓“螺旋矩阵”,是指从左上角第 1 个格子开始,按顺时针螺旋方向填充.要求矩阵的规模为 m 行 n 列,满足条件:m×n 等于 N:m ...

  4. PAT Basic 1065 单身狗 (25 分)

    “单身狗”是中文对于单身人士的一种爱称.本题请你从上万人的大型派对中找出落单的客人,以便给予特殊关爱. 输入格式: 输入第一行给出一个正整数 N(≤ 50 000),是已知夫妻/伴侣的对数:随后 N ...

  5. PAT Basic 1030 完美数列 (25 分)

    给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列. 现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列. 输入格 ...

  6. PAT Basic 1015 德才论 (25 分)

    宋代史学家司马光在<资治通鉴>中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人.凡取人之术,苟不得圣人,君子而与之,与其得小人,不若得愚人 ...

  7. PAT Basic 1070 结绳(25) [排序,贪⼼]

    题目 给定⼀段⼀段的绳⼦,你需要把它们串成⼀条绳.每次串连的时候,是把两段绳⼦对折,再如下图所示套接在⼀起.这样得到的绳⼦⼜被当成是另⼀段绳⼦,可以再次对折去跟另⼀段绳⼦串连.每次串 连后,原来两段绳 ...

  8. PAT (Basic Level) Practise (中文)-1035. 插入与归并(25)

    PAT (Basic Level) Practise (中文)-1035. 插入与归并(25)   http://www.patest.cn/contests/pat-b-practise/1035 ...

  9. PAT (Basic Level) Practise (中文)-1025. 反转链表 (25)

    PAT (Basic Level) Practise (中文)-1025. 反转链表 (25)   http://www.patest.cn/contests/pat-b-practise/1025 ...

随机推荐

  1. sendgrid 批量发送邮件,收件栏只显示当前用户的方案

    需求:批量发送邮件,用户可能看到其他用户的邮箱地址,之前用BBC发送,但问题是接收地址是同一个. 官方解决方案:https://sendgrid.kke.co.jp/docs/Tutorials/A_ ...

  2. nidlist 问题

    错误问题如下: 解决方案: Dao文件 boolean DeleteList(String nidList); 改为: boolean DeleteList(@Param("nidList& ...

  3. JAVA程序中常用概念介绍

    一.关键字.引用.直接量.变量.长量概念 1.关键字 java内部定义的java语言专用的单词,这些单词具有特殊含义,开发人员在定义自己声明的名称时,应该避开这些专用的单词.这些专用的单词也就称之为j ...

  4. hdu 3308 线段树,单点更新 求最长连续上升序列长度

    LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  5. android 开发学习2

    Dao dao = new Dao(yi_ji_lu_zhang_dan.this);List<GetOneRecord> list = dao.getAllRecord();//创建迭代 ...

  6. SpringAOP切入点的表达式

    1. 常用的切入点表达式分为:  (1)按类型匹配:within 关键字 (2)按函数匹配:execution (3)按bean的id匹配:bean 2.按类匹配的写法 匹配到具体的类:<aop ...

  7. oracle修改表名

    alter table 原来表名 rename to 新表名

  8. 欧拉回路--P2731 骑马修栅栏 Riding the Fences

    实在懒得复制题干了 *传送 1.定义 *如果图G(有向图或者无向图)中所有边一次仅且一次行遍所有顶点的通路称作欧拉通路. *如果图G中所有边一次仅且一次行遍所有顶点的回路称作欧拉回路. *具有欧拉回路 ...

  9. Linux 压缩解压操作

    Linux 压缩解压操作 Linux解压文件到指定目录 tar在Linux上是常用的打包.压缩.加压缩工具,他的参数很多,折里仅仅列举常用的压缩与解压缩参数 参数:-c :create 建立压缩档案的 ...

  10. 吴裕雄--天生自然Django框架开发笔记:Django Nginx+uwsgi 安装配置

    Django Nginx+uwsgi 安装配置 使用 python manage.py runserver 来运行服务器.这只适用测试环境中使用. 正式发布的服务,需要一个可以稳定而持续的服务器,比如 ...