关闭

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

标签: 计算机数据结构
27人阅读 评论(0) 收藏 举报

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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:29次
    • 积分:10
    • 等级:
    • 排名:千里之外
    • 原创:1篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类
    文章存档