算法导论 9.3-8 寻找数组X[1..n],Y[1...n] 合并后的中位数

该博客探讨了如何在O(logn)的时间复杂度内找到两个已排序数组X和Y合并后的中位数。通过中位数的二分查找策略,作者介绍了初步的解决方案,并引用了其他博主的改进方法,解决了算法在某些情况下可能出现的常数项偏移问题。代码示例展示了这一过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:找两个已经排序的数组X[1..n],Y[1...n] 合并后的中位数,要求算法时间是logn。

稍微想了一下,利用中位数的思想来进行二分,这样就可以在logn的时间内找到中位数。按照这个思想写出来的代码在一定概率下能够找到中位数,但是有些情况发会发生常数项的偏移。后来看 “正在跟新昵称“ 童鞋的blog,发现他进行了很好地修正。 十分感谢。 附上代码:

#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
using namespace std;
int * generateArray(int n);
void printArray(int *A,int p,int r);
void FindMiddle(int*A,int *B,int n);
void vilentMiddle(int *A,int *B,int n);
void FindMiddleB(int*A,int *B,int n);
int main ()
{
    srand(time(NULL));
    int k = 15;
    int *A = generateArray(k);
    printArray(A,0,k);
    int *B = generateArray(k);
    printArray(B,0,k);
    FindMiddle(A,B,k);
    //FindMiddleB(A,B,k);
    vilentMiddle(A,B,k);

}
int * generateArray(int n)
{

    int *A = new int[n];
    for (int i =0;i < n;i ++)
    {
        A[i] = rand();
    }
    sort(A,A+n);
    return A;
}
void printArray(int *A,int p,int r)
{
    for (int i = p;i < r;i ++)
    {
        cout << A[i] <<'\t';
    }
    cout <<endl << "--------------------------------" << endl;
}
void FindMiddle(int*A,int *B,int n)
{
    int sa = 0,sb = 0;
    int ea = n-1, eb = n-1;
    int ma = 0,mb = 0;
    if (A[n-1] <= B[0])
    {
        cout << A[n-1] << ' ' <<B[0] <<endl;
        return;
    }
    if (B[n-1] <= A[0])
    {
        cout <<B[n-1] << ' ' << A[0] <<endl;
        return;
    }
    while (sa < ea && sb<eb)
    {
        ma = (ea+sa)/2;
        mb = (eb+sb)/2;
        if (A[ma] < B[mb])
        {
            sa = ma;
            eb = mb;
        }
        else
        {
            ea = ma;
            sb = mb;
        }
    }
    int t = ma + mb +2;
    cout <<t <<endl;
    cout << n-t << endl;

    bool flag = false;
    if (n-t > 0)//进行修正
    {
        for (int i = 1; i <= n-t; i ++)
        {
            ++ma;
            ++mb;
            if(A[ma] < B[mb])
            {
                cout << "as" << A[ma] << ' '<< B[mb] <<  endl;
                --mb;
                flag = false;
            }
            else
            {
                cout << "ds" << A[ma] << ' '<< B[mb] <<  endl;
                --ma;
                flag = true;
            }
        }
        if (flag)
        {
            cout << B[mb] <<endl;
        }
        else
        {
            cout << A[ma] << endl;
        }
    }
    else
    {
        if (A[ma] < B[mb])
        {
            cout << B[mb] <<endl;
        }
        else
        {
            cout <<A[ma] << endl;
        }
    }


   // cout << A[ma] << ' ' << B[mb] <<endl;
   /* if (true)
    {
        cout << A[sa] << ' ' << A[ea] <<endl << B[sa] << ' ' << B[ea] <<endl;
    }
    else{
        cout << A[ma] <<endl;
    }*/

}


void FindMiddleB(int*A,int *B,int n)
{
    int sa = 0,sb = 0;
    int ea = n-1, eb = n-1;
    int ma = 0,mb = 0;
    if (A[n-1] <= B[0])
    {
        cout << A[n-1] << ' ' <<B[0] <<endl;
        return;
    }
    if (B[n-1] <= A[0])
    {
        cout <<B[n-1] << ' ' << A[0] <<endl;
        return;
    }
    while (sa < ea && sb<eb)
    {
        ma = (ea+sa+1)/2;
        mb = (eb+sb+1)/2;
        if (A[ma] < B[mb])
        {
            sa = ma;
            eb = mb;
        }
        else
        {
            ea = ma;
            sb = mb;
        }
    }
    int t = ma + mb +2;
    cout <<t <<endl;
    cout << n-t << endl;
    cout <<A[ma] << ' ' << B[mb] <<endl;
    bool flag = false;
    if (t-n-1> 0)
    {
        for (int i = 1; i <= t-n-1; i ++)
        {
            --ma;
            --mb;
            if(A[ma] < B[mb])
            {
                cout << "as" << A[ma] << ' '<< B[mb] <<  endl;
                ++ma;
                flag = false;
            }
            else
            {
                cout << "ds" << A[ma] << ' '<< B[mb] <<  endl;
                ++mb;
                flag = true;
            }
        }
        if (flag)
        {
            cout << B[mb] <<endl;
        }
        else
        {
            cout << A[ma] << endl;
        }
    }
    else
    {
        if (A[ma] < B[mb])
        {
            cout << B[mb] <<endl;
        }
        else
        {
            cout <<A[ma] << endl;
        }
    }


   // cout << A[ma] << ' ' << B[mb] <<endl;
   /* if (true)
    {
        cout << A[sa] << ' ' << A[ea] <<endl << B[sa] << ' ' << B[ea] <<endl;
    }
    else{
        cout << A[ma] <<endl;
    }*/

}


void vilentMiddle(int *A,int *B,int n)
{
    int *C = new int[2*n];
    for (int i = 0;i < n;i ++)
    {
        C[i] = A[i];
        C[i+n] = B[i];
    }
    sort(C,C+2*n);
    cout << C[n-1] <<' ' <<C[n] << endl;
    printArray(C,0,2*n);
    delete []C;
}

上面一段代码中,修正最终结果的那段代码虽然是可以用的,但是不知道怎么推出来的。囧。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值