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

来源:互联网 发布:手机测试分贝软件 编辑:程序博客网 时间:2024/05/17 02:31

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)

0 0
原创粉丝点击