[PAT Basic Level] 1035. 插入与归并

题目分析:

这道题目,花了不少时间,犯了一个很窒息也让我查了很久很才发现的错误——把Insertion Sort输出成了Insert Sort。。。写这道题的分析时,身心俱疲。中途因为查不出错,借鉴了网上的一些代码并相应地修改了,所以和网上很多其他人代码比较相似。

这道题目从0~6一共7个测点,0、2、4是插入排序测点,其余是归并排序测点(看看我的错误想必就能明白为何我知道这些测点的情况了。。)

把思路弄清楚其实写起来倒也不太麻烦,首先关于判定是何种排序,可以先找出第一个未排好序数据的位置,若第一个未排好序及之后的每一个数都与原序列对应相等,那么一定是插入排序,否则就是归并排序。当然这个判断其实仅适合这道题目,很容易看出来这个判断有很大的漏洞,不过题目说了给出的序列不会有歧义,所以放心大胆用就行。

另外,在这里需要说明和强调一下,网上不少相关的博客其实说的不对,肯定没经过自己认真思考,题目这里的归并排序并不是递归版递归版的归并排序会把序待排序列分成两半,先将左半部分全部排完,才会开始对右半部分进行排序,也就是说前面几步排序后,序列后半部分很可能是不会有变化的。

明确了这个要求后,编写再排序一步的算法也就比较容易了。归并排序进一步排序的算法,在修改代码时以为是自己真的写错了就按人家的改了。。。后来发现原因竟然是printf的问题。。心太累就不想再重新写一遍改回原来的了。在后面简单介绍一下我之前的算法思路。
现在的代码和网上其他类似,但有修改。在这里一遍遍地排序时,越到后面数组越来越有序,而在数组基本有序的情况下,插入排序就的性能就会高很多,本身已经有序时的复杂度是 O ( n ) O(n) O(n),所以在这里我写了简单的插排。(不过题目数组长度小,最多就100,随你怎么折腾,写个冒泡排序都不会有问题)。

为了进一步发挥插排的性能,我没有向网上很多人那样从原始数组出发排序直到与部分排序数组相等,而是选择从部分排好序的数组出发,逐步进行区间排序,直到某次排序后数组发生了变化,即说明新进行了一轮归并排序,可以停止并输出了。

我之前采用的方式是按照归并排序的思路,找出最短的未排好序的区间长度d,然后再以此区间长度排序一遍即可,判断数组未排序好的区间长度的代码实际上不会出现重复判断,所以最多对n个元素各自比较一次,这个函数复杂度是 O ( n ) O(n) O(n),而给出长度后再排一步也很容易实现复杂度为 O ( n ) O(n) O(n)的代码,从渐进意义上来说我之前的算法比我现在按照网上其他代码修改的算法好,但是写起来稍微复杂点,而题目在复杂度上基本没啥要求,在PAT这种以写的快能过为目的的条件下,这么干意义就不是很大了。

源代码

#include <stdio.h>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值