求两个有序序列的中位数。(要求时间复杂度为O(logN))

18 篇文章 0 订阅


1.实践题目

求两个有序序列的中位数。(要求时间复杂度为O(logN))

2. 问题描述

已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列A0, A1…AN-1的中位数指A(N-1)/2的值,即第[(N+1)/2]个数(A0为第1个数)。

3.算法描述

总体思想:采用分治与递归策略,二分法每次将问题规模减半(约减半),然后对问题进行递归处理,在进行递归的过程中对可能出现特殊的情况,就特殊安排处理。

详细算法步骤:

① 先排除两个等长序列的元素个数(奇和偶)的影响,首先对两个序列求中位数,求中位数的方法是如下,此方法为保证偶数序列的分割保持割后对称性,而对奇数序列不产生影响,如此可以保证递归的时候子问题也是两个等长的序列。






对两个数组的左右两端初始化后便进入函数。

② (在两端标志还未出现相等或者其他特殊情况时,下文将说)每次求得两个序列的中位数(如果序列是偶序列,则第二个序列的中位数定为A【(N-1)/2 + 1】,即中位数的后一个数),将两个中位数进行比较,若两数相等的话,则可确认为此数为所求中位数。若不相等,则对两个数中较大的数的那一序列进行减掉比这个数大的(即这个数后面)的部分,保留其他;对另一个序列(较小数所在序列)而言,则减掉比它小的(即前面的)部分,保留其他,比较后,对剩下的等长序列进行递归调用。

③ 在进行递归过程中,若还未出现相等中位数,两序列的两端标志将会不断靠近,所以此时对于实例不同的序列,就会可能出现一些特殊情况,所以下面就讲解对于所有可能出现特殊情况的解决办法,第一种情况是当两序列都只剩最后一个时,就对两数进行比较,小的为所求中位数。

 

第二种情况为当两序列都最后只剩两个数而无法再进行递归下去(陷入死循环)时,我想到的解决办法是

第一个序列求中位数方法不变,第二个序列变为与第一序列相同的方法求得中位数,在这样的处理下再进行递归一次,所以之后两个共剩下三个数,就分两种情况,第一种为第一个序列剩一个,第二种为第二个序列剩一个,两种情况的解决方案都为:然后把剩一个的那组的数与剩两个那组的较大的数(也就是第二个数)进行比较,取小的那个数,那个数就是我们所求中位数。

完整代码如下:

#include<iostream>
using  namespace std;
 
 
int MidSerch(int a[], int b[], int la, int ra, int lb, int rb) {
int ma = (la + ra) / 2;
int mb = (lb + rb+1) / 2;
if (la == ra&&lb != rb) {
if (a[la] > b[rb])return b[rb];
else return a[la];
}
if (lb == rb&&la != ra) {
if (b[lb] > a[ra])return a[ra];
else return b[lb];
}
 
if (la == ra&&lb == rb) {
if (a[la] > b[lb])return b[lb];
else return a[la];
}
else
{    if (la == ra - 1 && lb == rb - 1) 
    {
ma = (la + ra) / 2;//第一个序列求中位数方法不变
mb = (lb + rb) / 2;//第二个序列变为与第一序列相同的方法求得中位数
//但由于元素个数只有两个,所以括号内可写为:mb = mb - 1;
    }
if (a[ma]==b[mb])
{
return a[ma];
}
else if (a[ma] > b[mb]) {
MidSerch(a, b, la, ma ,mb, rb);
}
else{
MidSerch(a, b, ma, ra, lb, mb);
}
 
}
} 
 
 
int main() {
int n;
cin >> n;
    int *a = new int[n];
int *b = new int[n];
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
for (int i = 0; i < n; i++)
{
cin >> b[i];
}
 
cout<<MidSerch(a, b, 0, n - 1, 0, n - 1);
 
system("pause");
}


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

由于采用递归二分策略,每次将问题分成规模减半的子问题(即所说的不断二分),所以消耗的时间是(时间复杂度)O(logN),再加上特殊情况的比较和比较所用的常数时间,时间复杂度还是为O(logN)。对于空间复杂度,由于只开辟了几个变量的地址和数据,所以空间复杂度为O(1);

5. 程序运行截图

 

6.心得体会——对本次实践收获及疑惑进行总结

本次问题主要考核二分法解决实际问题,但是要注重考虑时间复杂度,和所处理特殊情况的解决方案。要学会思考,不能盲目跟从,很多问题不单只有一个解决方案,也可以达到要求。对于思考解决问题的算法,可以首先在纸上用笔去研究一些实例,再总结出通法,以达到解决普遍问题和顾及到所有特殊情况。




 

  • 10
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值