算法实验报告 排序类

E1-1

Problem

在数据库中查找对应key的index

V1
思路:

直接使用遍历的方法,每次查找都遍历一遍数组,如果遍历直至结束都没有找到与k相同的数字,输出-1

时间复杂度

时间复杂度:每次遍历寻找的时间复杂度是O(n)

细节&问题
  • 第一次用了很多库函数来处理输入gets()、atoi()、double log10(double) 等等,但是出现了很多的runtime error
  • 输入的ID直接用数组下标表示,用strcmp() 匹配输入的模式
  • 因为查找范围的问题,也不清楚输入的ID是不是顺序输入的(从1开始),为了防止出错,开始的时候把DB数组里的内容全部置为-1
  • 开始开了一个109的数组,出现了recolation truncated to fit的问题,查资料之后发现出现了内存的限制,改成了106+1大小
V2
思路

用结构体记录ID和key,根据ID进行排序(使用了快排),再用二分查找实现查找的功能

时间复杂度

排序的时间复杂度O(nlogn),二分查找时间复杂度O(logn),总体时间复杂度O(nlogn)

细节&问题
  • 这次改用朴素的scanf 和getchar搭配处理输入,没有再出现前面的问题
  • 可能是我第一次对于ID的想法出现了偏差,插入数据库中的ID不一定是从1开始的有序的数,所以像第一版思路里面的直接使用下标表示可能会发生越界

E1-2

Problem

求逆序对的问题

思路

应该有两种基本思路,第一种是依次遍历每个元素再遍历它后面的元素,这样的话时间复杂度是O(n2),估计会超时

第二种采用Divide and Conquer 的方法,具体来说应该是先Divide两边的元素排好序之后在merge的过程中如果左边的元素小于右边直接放进排好序的数组中,如果大于右边的话,那这个元素后面的每一个元素一定都比序列2中的这个元素大,这样就找出来逆序对。

时间复杂度

由于过程是递归的也不会有遗漏,每次只是在比较之后增加了一个计算过程,所以时间复杂度仍然是O(nlogn)

问题&细节
  • 第一次计数值使用的数据类型是int,出现了后面几个是wrong answer的问题,出现的原因应该是这个数值很大的时候使用int会出现溢出,所以要使用long的数据类型

E1-3

Problem

无序数列在排序之后求相邻两个数的差的最大值

思路

最直观的思路是使用一个O(nlogn)的排序算法排完序之后,再依次求差值,并求出差值的最大值,这样一来的时间复杂度是O(nlogn + n),总觉得不太聪明的样子

在网上查找了一些类似的算法题,发现它们要求时间复杂度在O(n)

总结了看到的一些算法之后我的思路如下,借用桶排序的方法,但是由于桶排序的输入假设比较奇怪,所以具体实现上有所不同。

大致步骤如下:

  1. 首先确定最大值和最小值
  2. 将n个元素放在n+1个桶中,除了最后一个桶放置max元素之外,其他n个桶cover的范围是(max-min)/n。
  3. 注意到一定会有一个空桶,在空桶左边的最大值和右边的最小值在有序的情况下在数列中一定是相邻的,而且差值一定比桶的范围大
  4. 找到空桶两边的最大值就可以确定数列有序之后相邻两数差的最大值
时间复杂度

首先需要找到最大值和最小值,时间复杂度为O(n), 桶排序的时间复杂度是O(n),在这个基础上,需要O(n)的时间遍历是否是空桶,并求出空桶两边的最大最小值的差,所以整体的时间复杂度仍是O(n)

问题&细节
  • 找到最大,最小值的过程可以在输入的时候实现
  • 确定数字放在哪一个桶中,假设数是a 那么除了max之外,(a-min)/(max-min)的范围就是在[0,1)之间,符合桶排序的输入要求,那么所在的桶的序号就是n*(a-min)/(max-min) 取下整
  • 理论上桶排序的每个桶应该使用链表的形式,但是因为这里只和每个桶的最大值或者最小值有关,所以只用规模为n+1的两个数组记录最大值和最小值,同时还需要一个数组记录这个桶是否是空桶
  • 最后遍历求Maxgap的时候需要一个变量记录前面最近的一个非空桶的最大值,和后面最近的一个非空桶的最小值
  • 经过上一道题的教训,我决定将输入的n和整数的类型全部定义为long
  • 又一次出现了RE,在检查了所有的数组index没有越界之后,意识到可能是因为在函数里面开了太大的数组导致栈溢出了,改成全局变量之后就AC了

E1-EX

Problem

求出数组的连续子数组中的最大值

思路

我的思路是先求第一个k数组的最大值,需要返回最大值和下标,后面每次子数组右移减少了一个值如果这个值是最大值(需要再求一遍),否则最大值不变。如果加入的值比现有的最大值大的话加入的值变成最大值,否则输出最大值。

时间复杂度

Worst case: 如果数组完全倒序输入,每次的时间复杂度都是O(k),那么整体的时间复杂度就是O(k*(n-k+1))

Best Case: 第一个数组一定会遍历一遍时间复杂度O(k),在best case的情况下后面的每一次只需要做一次比较操作,整体的时间复杂度是O(n)

问题&细节
  • 我觉得这个算法非常愚蠢,尤其是在Worst Case下面,但是代码写起来非常快乐因为很简单,最后可能是因为这个小明可以预测的时间不算很长所以k比较小,超时的情况并没有发生

  • 有点没有get到为什么这道题难度是High

    最后,这次实验告诉我在oj里面,特别是变量的范围很大,可能要开很大的数组的时候,在函数里面开极易导致Runtime Error,这时候一定要用全局变量!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值