求解两个等长升序序列的中位数

原创 2016年08月30日 20:46:20

2011年计算机联考真题

题目描述:

    一个长度为L (L>=1)的升序序列S,处在第[L/2]个位置的数称为S的中位数。例如,若序列S1=(11, 13, 15, 17, 19),则S1的中位数是15,两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若S2= (2, 4,6,8, 20),则S1和S2的中位数是11。现在有两个等长升序序列A和B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列A和B的中位数。

递归解法:

基本思想:

    我们找到了A[n/2] 和 B[n/2]来比较,
    如果他们相等,那样的话,我们的搜索结束了,因为答案已经找到了A[n/2]就肯定是排序后的中位数了。
    如果我们发现B[n/2]>A[n/2],说明什么,这个数字应该在 A[n/2]->A[n]这个序列里面, 或者在 B[1]-B[n/2]这里面。
    类似的, 如果B[n/2]<A[n/2]呢?显然就是在A[0]-A[n/2]和B[n/2]-B[n]里面寻找了。
    这个递归什么时候结束呢?当然一种情况就是相等的值出现, 如果不出现等到这个n==1的时候也就结束了。

注意:

    当元素个数为奇数时舍弃中间点以前或以后部分,保留中间点
    当元素个数为偶数时:往前舍的舍掉中间点,往后舍得保留中间点,这是为了保证元素个数始终相同

代码如下:

int Find_Median( int a[], int b[], int length)
{
    if (length == 1)
        return a[0] < b[0] ? a[0] : b[0];

    int i = (length - 1)/2;
    if (a[i] == b[i])
        return a[i];
    else if(length % 2 == 0)
    {
        if (a[i]<b[i])
            // 舍掉a的中间点及以前部分,b保留中间点
            return Find_Median( &a[i+1], &b[0], length-i-1 );
        else
            //舍掉b的中间点及以前部分,a保留中间点
            return Find_Median( &a[0], &b[i+1], length-i-1 );
    }
    else
    {
        if (a[i]<b[i])
            return Find_Median( &a[i], &b[0], length-i );
        else
            return Find_Median( &a[0], &b[i], length-i );
    }
}

非递归解法

基本思想:

分别求两个序列的中位数,设为a, b,求A、B的中位数的过程如下:
     1、若a = b, 则a或b为所求,算法结束;
     2、若a < b, 则舍弃A中较小的一半,同时舍弃B中较大的一半,要求两次舍弃的长度相等;
     3、若a > b, 则舍弃A中较大的一半,同时舍弃B中较小的一半,要求两次舍弃的长度相等。
     重复步骤1 2 3,直到两个序列均只含一个元素,较小者即为所求

代码如下:

// 非递归版本
int M_Search(int A[], int B[], int n)
{
    //A、B的首位数、末位数和中位数
    int s1 = 0, d1 = n-1, s2 = 0, d2 = n-1, m1, m2;
    while(s1 != d1 || s2 != d2)
    {
        m1 = (s1 + d1)/2;
        m2 = (s2 + d2)/2;
        //满足条件 1
        if(A[m1] == B[m2])
            return A[m1];
        //满足条件 2
        if(A[m1] < B[m2])
        {
            //元素个数为奇数
            if((d1 + s1)%2 == 0)
            {
                s1 = m1;
                d2 = m2;
            }
            //元素个数为偶数
            else
            {
                s1 = m1 + 1;
                d2 = m2;
            }
        }
        //满足条件 3
        else
        {
            //奇数
            if((d2 + s2)%2 == 0)
            {
                d1 = m1;
                s2 = m2;
            }
            //偶数
            else
            {
                d1 = m1;
                s2 = m2 + 1;
            }
        }
    }

    return A[s1] < B[s2] ? A[s1] : B[s2];
}

两种算法时间复杂度均为O(logn)

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

减治法求解两个升序数组的中位数

#include using namespace std; int SearchMid(int a[],int b[],int n){ int s1=0,e1=n-1,s2=0,e2=n-1; ...

求两个升序序列的中位数

这里涉及到数据结构中顺序表的实现、删除、插入、查找等知识,请查看:数据结构 -> 线性表 问题描述: 一个长度为L (L>=1)的升序序列S,处在第[L/2]个位置的数称为S的中位数。例如,若...

2-13. 两个有序序列的中位数(25)(ZJU_PAT 链表 | 数组 )

2-13. 两个有序序列的中位数(25)(ZJU_PAT 链表 | 数组 )

寻找两个不等长数组的中位数 Median of Two Sorted Arrays

题目源自于Leetcode。经典好题。 题目: 给出两个有序数组,长度不一定相同,一个是m一个是n,要求给出他们合并在一起之后的数组的中位数。 要求时间复杂度为O(log(m+n)),所以不可以合并数...

【算法导论学习-016】两个已排过序的等长数组的中位数(median of two sorted arrays)

求两个已排过序的等长的数组的中位数(median of two sorted arrays)

MDX示例:求解中位数、四分位数(median、quartile)

采集获取知名招聘网站上的求职和招聘信息并通过商业智能开展职业职位供求及趋势等相关统计分析。何用MDX求解薪水中位数、四分位数(Median,Quartile)等。

中兴笔试题:两有序数组的中位数求解

题目:设X[1..n]和Y[1..n]为两个数组,每个都包含n个已排好序的数。给出一个求数组X和Y中所有2n个元素的中位数的、O(lgn)时间的算法。         首先假设中位数等于m,在数组X...

双层桶-中位数求解

fstream操作参考:http://www.cppblog.com/saga/archive/2007/06/19/26652.html 题目描述: 101个数

两个序列的中位数

  • 2012-03-30 11:16
  • 1008B
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)