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语言
根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序. 归并排序进行如下迭 ...
随机推荐
- JS 表单相关
var title = $("#subjects option:selected").text();
- MySQL 之存储引擎与数据类型与数据约束
一.存储引擎场景 1.InnoDB 用于事务处理应用程序,支持外键和行级锁.如果应用对事物的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包括很多更新和删除操作,那 ...
- C语言中的结构体是怎么定义的_怎么使用?
结构体的定义 // 定义结构体st struct st{ int a; // 成员a int b; // 成员b }; #include <stdio.h> struct st{ int ...
- Java8 HashMap详解
Java8 HashMap Java8 对 HashMap 进行了一些修改,最大的不同就是利用了红黑树,所以其由 数组+链表+红黑树 组成. 根据 Java7 HashMap 的介绍,我们知道,查找的 ...
- 使用oracle 的 PL/Sql 定时执行一个存储过程
CSDN日报20170322--<关于软件研发的一些体会总结> 同步博客至 CSDN ,让更多开发者看到你的文章 看微博技术大咖解析互联网应用架构实战 使用oracle 的 PL/Sql ...
- [Linux] day03——REHL部署
REHL 部署 Linux 树形目录结构 最顶层 根 / 在Linux中 一切皆文件 文件系统 swap / 安装方式 PXE U盘 光盘 配置安装程序 选择包 5.9 6.4
- 十九 Spring的JDBC模版使用: 模版的CRUD的操作
Spring的JDBC模版使用: 模版的CRUD的操作 保存操作 修改操作 删除操作 查询操作 import com.ithheima.jdbc.domian.Account; @RunWith(Sp ...
- QQ企业通--客户端登陆模块设计---知识点2
Maximizable 属性 获取一个值,该值指定窗口是否可以最大化. fromBorderstyle 成员名称 说明 None 无边框. Fi ...
- myBatis 操作 mysql时,使用 like 关键进行模糊查询的方法
参考:https://blog.csdn.net/rainbow702/article/details/50519424 like CONCAT('%', #{mkName}, '%')
- Keras入门——(5)长短期记忆网络LSTM(二)
参考: https://blog.csdn.net/zwqjoy/article/details/80493341 https://blog.csdn.net/u012735708/article/d ...