P 1035 插入与归并
转跳点 :
根据维基百科的定义:
插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。
归并排序进行如下迭代操作:首先将原始序列看成 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
这道题比较有意思,需要用到归并排序和插入排序的知识,两种排序的博客我都写了,自行转跳。
这道题有两种解法,
第一种是写两个排序算法,每执行完一轮就比较一次,时间复杂度 T(O) = O(N^3+N^2logN),太暴力了
第二种是利用插入排序的特性:插入排序,前面是排好序的,后面是与初始序列相同。只要符合这个条件的就是插入,不符合就是归并
用第一种方法暴力就行,但是第二种就需要对归并和插入排序十分熟悉,因为要写一个单步的归并和插入。插入的单步十分容易实现只要知道第几个没排好,继承索引,找到位置插入就行了。而归并就有些麻烦,需要完完整整的归并。
AC代码
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 int Merge = 0;
6 void InsertSorted(int arr[], int mid[], int n);
7 void MergeSorted(int arr[], int mid[], int n);
8 int ArrayEqual(int arr[], int ary[], int n);
9 void ArrayPrint(int arr[], int n);
10
11 int main(void)
12 {
13 static int n;
14 int arr[101];
15 int ary[101];
16 int mid[101];
17
18 scanf("%d", &n);
19
20 for (int i = 0; i < n; i++)
21 {
22 scanf("%d", &arr[i]);
23 ary[i] = arr[i];
24 }
25
26 for (int i = 0; i < n; i++)
27 {
28 scanf("%d", &mid[i]);
29 }
30
31 InsertSorted(arr, mid, n);
32 if (Merge)
33 {
34 MergeSorted(ary, mid, n);
35 }
36
37 return 0;
38 }
39
40 //插入排序
41 void InsertSorted(int arr[], int mid[], int n)
42 {
43 int j, temp;
44
45 for (int i = 1; i < n; i++)
46 {
47 j = i;
48 temp = arr[i];
49 while (j > 0 && temp < arr[j - 1])
50 {
51 arr[j] = arr[j - 1];
52 j--;
53 }
54 arr[j] = temp;
55
56 if (ArrayEqual(arr, mid, n))
57 {
58 j = ++i;
59 temp = arr[i];
60 while (j > 0 && temp < arr[j - 1])
61 {
62 arr[j] = arr[j - 1];
63 j--;
64 }
65 arr[j] = temp;
66 printf("Insertion Sort\n");
67 ArrayPrint(arr, n);
68 Merge = 0;
69 return;
70 }
71 }
72 Merge = 1;
73 }
74
75 void MergeAdd(int arr[], int left, int mid, int right, int *tmp)
76 {
77 int i = left;
78 int j = mid + 1;
79 int k = left;
80 while (i <= mid && j <= right)
81 {
82 tmp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
83 }
84 while (i <= mid)
85 {
86 tmp[k++] = arr[i++];
87 }
88 while (j <= right)
89 {
90 tmp[k++] = arr[j++];
91 }
92 //把tmp中的内容拷给arr数组中
93 //进行归并的时候,处理的区间是arr[left,right),对应的会把
94 //这部分区间的数组填到tmp[left,right)区间上
95 memcpy(arr + left, tmp + left, sizeof(int) * (right - left + 1));
96 }
97
98 void MergeSort(int arr[], int len, int *tmp, int mid[], int n)
99 {
100 if (len <= 1)
101 {
102 return;
103 }
104 int flag = 0;
105
106 //定义一个步长gap,初始值为1,相当于每次只合并两个长度为1的元素
107 for (int gap = 1; gap <= len; gap *= 2)
108 {
109 for (int i = 0; i <= len; i += 2 * gap)
110 {
111 int beg = i;
112 int mid = (gap - 1) + i;
113 if (mid >= len)
114 {
115 mid = len;
116 }
117 int end = mid + gap;
118 if (end >= len)
119 {
120 end = len;
121 }
122 MergeAdd(arr, beg, mid, end, tmp);
123 }
124 if (flag)
125 {
126 printf("Merge Sort\n");
127 ArrayPrint(arr, n);
128 return;
129 }
130 if (ArrayEqual(arr, mid, n))
131 {
132 flag = 1;
133 }
134 }
135 }
136 //归并排序接口
137 void MergeSorted(int arr[], int mid[], int n)
138 {
139 int *temp = malloc(sizeof(int) * n);
140 MergeSort(arr, n - 1, temp, mid, n);
141 free(temp);
142 }
143 //输出数组
144 void ArrayPrint(int arr[], int n)
145 {
146 for (int i = 0; i < n; i++)
147 {
148 printf("%d%s", arr[i], n - 1 == i ? "" : " ");
149 }
150 }
151 //判断相等
152 int ArrayEqual(int arr[], int ary[], int n)
153 {
154 for (int i = 0; i < n; i++)
155 {
156 if (arr[i] != ary[i])
157 {
158 return 0;
159 }
160 }
161 return 1;
162 }
第二种:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int isinsertion(int n, int num[], int mid[]);
5 int nextmerge(int n, int num[], int mid[]);
6 int cmp(const void *a, const void *b) { return (*(int *)a) > (*(int *)b); }
7
8 int main()
9 {
10 int n, num[100], mid[100];
11 int i;
12 scanf("%d", &n);
13 for (i = 0; i < n; i++)
14 {
15 scanf("%d", &num[i]);
16 }
17 for (i = 0; i < n; i++)
18 {
19 scanf("%d", &mid[i]);
20 }
21
22 if (isinsertion(n, num, mid))
23 {
24 nextmerge(n, num, mid);
25 }
26
27 for (i = 0; i < n; i++)
28 {
29 printf("%d%s", num[i], i == n - 1 ? "" : " ");
30 }
31 return 0;
32 }
33
34 int isinsertion(int n, int num[], int mid[])
35 {
36 int i, lenth;
37 for (i = 0; i < n - 1 && mid[i] <= mid[i + 1]; i++)
38 {//前面是排好序的
39 continue;
40 }
41 for (i++, lenth = i; i < n && mid[i] == num[i]; i++)
42 {//后面是与初始序列相同
43 continue;
44 }
45 if (i < n)
46 {
47 return 1;
48 }
49 printf("Insertion Sort\n");
50 lenth++;
51 qsort(num, lenth, sizeof(int), cmp);
52 return 0;
53 }
54
55 int nextmerge(int n, int num[], int mid[])
56 {
57 int i, j, lenth;
58 printf("Merge Sort\n");
59 for (lenth = 1, i = 0; i < n && lenth <= n; lenth *= 2)
60 { //只能一步步归并
61 for (i = 0; i < n && num[i] == mid[i]; i++)
62 ;
63 for (j = 0; j < n / lenth; j++)
64 {
65 qsort(num + j * lenth, lenth, sizeof(int), cmp);
66 }
67 qsort(num + j * lenth, n % lenth, sizeof(int), cmp);
68 }
69 return 0;
70 }
偷懒了,用qsort”实现“归并
PTA不易,诸君共勉!
P 1035 插入与归并的更多相关文章
- PAT-乙级-1035. 插入与归并(25)
1035. 插入与归并(25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 根据维基百科的定义: 插入排序是迭 ...
- PAT 1035 插入与归并(25)(代码+思路+测试点分析)
1035 插入与归并(25 分) 根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到 ...
- PAT (Basic Level) Practise (中文)-1035. 插入与归并(25)
PAT (Basic Level) Practise (中文)-1035. 插入与归并(25) http://www.patest.cn/contests/pat-b-practise/1035 ...
- PAT(B) 1035 插入与归并(Java)
题目链接:1035 插入与归并 (25 point(s)) 参考博客:PAT乙级--1035(插入排序和归并)java实现熊仙森 题目描述 根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据, ...
- PAT——1035. 插入与归并
根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序. 归并排序进行如下迭 ...
- PAT 1035. 插入与归并(25)
根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序. 归并排序进行如下迭 ...
- PAT 1035 插入与归并
https://pintia.cn/problem-sets/994805260223102976/problems/994805286714327040 据维基百科的定义: 插入排序是迭代算法,逐一 ...
- PAT 1035 插入与归并(25)
原题:https://pintia.cn/problem-sets/994805260223102976/problems/994805286714327040传送门: 根据维基百科的定义: 插入排序 ...
- 1035 插入与归并 (25 分)C语言
根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序. 归并排序进行如下迭 ...
随机推荐
- 在这之后的两天又出现了w3wp进程找不到的情况了
在这之后的两天又出现了w3wp进程找不到的情况了,我做了什么操作呢?无非就是vs中给一个过程附加删除了了一些dll,然后不停的重新生成解决方案,生成成功后,要调试,发现进程又没了. 实验了上面的方法, ...
- JAVA项目开发之文档篇
转自链接:https://blog.csdn.net/Zonzereal/article/details/76704455
- kubernetes 1.17.2 kubeadm部署 证书修改为100年
[root@hs-k8s-master01 ~]# cd /data/ [root@hs-k8s-master01 data]# ls docker [root@hs-k8s-master01 dat ...
- 「SP11470」TTM - To the moon
题目描述 给定一段长度为 \(N\) 的序列 \(a\) 以及 \(M\) 次操作,操作有以下几种: C l r d :将区间 \([l,r]\) 中的数都加上 \(d\) Q l r :查询当前时间 ...
- Write-up-Toppo
关于 下载地址:点我 哔哩哔哩:哔哩哔哩 信息收集 vmnet8网卡,IP:192.168.131.144,开放web,ssh服务 ➜ ~ ip a show dev vmnet8 5: vmnet8 ...
- 把PHP大牛记下来,方便以后关注
本帖最后由 fish_study 于 2014-12-31 00:18 编辑 五四陈科学院博主54chen(陈臻),哥学社创始人,前人人网分布式存储nuclear研发人员,现关注erlang.hado ...
- 微信小程序中,如何实现显示,隐藏密码的功能
最近在搞小程序的开发,遇到隐藏,显示密码的功能的时候,电脑上调试没问题,但是手机上面点击却没有效果,必须要跳转到其他页面再跳回来,才能正常显示. 一时间搞得我很头疼,查找资料后,终于知道了是什么原因. ...
- WebApi如何接收前台传递过来的数组
var ids = ["111", "222", "333"];$.ajax({ url: host + '/User/deleteByID ...
- ffmpeg 学习:001-搭建开发环境
介绍 由于命令行的ffmpeg工具无法满足产品的性能要求,需要对视频流进行兼容.所以需要调试有关的参数. FFmpeg全名是Fast Forward MPEG(Moving Picture Exper ...
- Swift 语法糖then
then是一个swift初始化库,只有80几行的代码库,确可以让初始化变得很优雅. 1.使用then初始化AnyObject,这里以初始化控件为例 lazy var label = UILabel() ...