算法第二章 实践报告

1.   实践题目

已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列

​​的中位数指A_(N−1)/2的值,即第⌊(N+1)/2⌋个数(A_0为第1个数)。

 

输入格式:

输入分三行。第一行给出序列的公共长度N(0<N≤100000),随后每行输入一个序列的信息,即N个非降序排列的整数。数字用空格间隔。

 

输出格式:

在一行中输出两个输入序列的并集序列的中位数。

 

输入样例1:

5

1 3 5 7 9

2 3 4 5 6

输出样例1:

4

输入样例2:

6

-100 -10 1 1 1 1

-50 0 2 3 4 5

输出样例2:

1

2.   题目描述

给出两段非降序数字序列,用算法找出两段数字合并后的中位数,要求时间复杂度为O(logn)

3.   算法描述

一开始想的是老师上课讲的归并排序,将两段数列合并后直接去中间值,但后来老师说,排序最快的时间复杂度是O(nlogn),超过了题目要求的O(logn)

第二个想的方法是做一个永真循环将a数组和b数组的每个数对比一次,但这样的时间复杂度是O(n),也超过了题目要求的O(logn)。

于是小白的我不会了,去向班上的高手请教。

高手说了噼里啪啦一大堆,我听的似懂非懂,只好自己慢慢对着敲了一遍。

大致的意思是,通过一些规律总结,从而借助二分递归的方法,对两段数字分别求中位数。

1)      如果两段序列的中位数相等,那么合并后的中位数即为该数。

                 if (a[mid1] == b[mid2])

            return a[mid1];

 

 

 

2)      如果当第一段的中位数小于第二段的时候,那么两端合中位数一定在第一段中位数后面或第二段中位数前面,这时只取这两部分,再继续进行二分比较

if (a[mid1] < b[mid2]) {

                   if ((l1 + r1) % 2 == 0) {

                l1 = mid1;

                r2 = mid2;

                       }

                   else {

                l1 = mid1 + 1;

                r2 = mid2 ;

                       }

 

3)      如果当第一段的中位数大于第二段的时候,那么两段合中位数一定在第一段中位数前或第二段中位数后,这时只取这两部分,再继续进行二分比较

 

{

            if ((l1 + r1) % 2 == 0) {

                r1 = mid1;

                l2 = mid2;

                   }

                     else {

                r1 = mid1;

                l2 = mid2 +1;

                       }

               }

4.   算法时间及空间复杂度分析

l  二分法,递归,时间复杂度为O(logn)。

l  没用用其他的辅助空间,空间复杂度为O(1)。

5.   心得体会

首先,递归是算法之本,但递归的种类又有很多,需要比较深入地去学习。

比如本次的实践题目第三题,用一般的归并,遍历就很难得到想要的结果,而班上同学想出来的二分法递归就很好地契合了O(logn)时间复杂度的要求

 

其次,作为小白的我对于算法了解的不多,所以我知道,需要多向厉害的同学请教,比如这次的题目,在自己想不出来的情况下,勇敢地向同学求助,集思广益,学习后,自己动手操作几次,也能学到不少东西。

上一篇:Tomcat 是怎样处理 SpringBoot应用的?


下一篇:PAT乙级1040(C++)——龙哥哥的刷题路