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语言
根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序. 归并排序进行如下迭 ...
随机推荐
- web组件化开发第一天
技术选型 html5 css3 jq 应用的插件 FullPage.js 一.建一个测试页面,测试静态的功能 <!DOCTYPE html> <html> <head&g ...
- 「CF1303C Perfect Keyboard」
前置芝士 图的遍历:通过DFS或者BFS遍历全图. 前向星:用来存边,但是在本题用也可以用一个二维数组解决. 具体做法 先从判断YES和NO开始,可以发现如果一个字母与三个及以上不同的字母相邻时肯定是 ...
- Qt 调用本地浏览器打开URL
点击Qt某些控件,查找本地浏览器打开前端传递的URL. 方法一:直接写死本地浏览器地址 QString programAdress = "C:\Program Files (x86)\Goo ...
- Python 基础之返回值与函数使用与局部变量和全局变量locals() 和 globals()
一.函数的返回值 return return: 自定义返回值,返回到哪里? 返回到函数的[调用处]1.return 后面可以跟上六个标准数据类型,除此之外,可以跟上 类对象,函数,如果不写return ...
- SVN commit,update用法
https://blog.csdn.net/studyvcmfc/article/details/4528896
- pip使用镜像的方法
http://e.pypi.python.org/这个就是官网了,清华大学提供的 建议非清华大学校内的使用这个镜像: http://e.pypi.python.org/simple(这也是一个http ...
- js去后台传递的值
function test(){ var param = [[${list}]];//以集合为例 } 如果list里面是实体类那么就需要重写toString,或者转为json
- Laradock 如何通过 ssh 方式连接到 workspace
用 docker-compose exec workspace bash 方式可以进入容器,但是还是在 xshell 终端连接比较方便. 在网上也没找到方法,其实可以通过密钥的方式连接.记录一下仅 ...
- 转:Nginx 性能优化有这篇就够了!
目录: https://mp.weixin.qq.com/s/YoZDzY4Tmj8HpQkSgnZLvA 1.Nginx运行工作进程数量 Nginx运行工作进程个数一般设置CPU的核心或者核心数x2 ...
- 6、mysql事务
1.mysql事务 —mysql中,事务其实是一个最小的不可分割的工作单元.事务能够保证一个业务的完整性,例如:银行存款: a - > -100 >update user set ...