lintcode(2)——两个排序数组的中位数

65. 两个排序数组的中位数

中文English

两个排序的数组A和B分别含有m和n个数,找到两个排序数组的中位数,要求时间复杂度应为O(log (m+n))。

样例

样例1

输入:
A = [1,2,3,4,5,6]
B = [2,3,4,5]
输出: 3.5

样例2

输入:
A = [1,2,3]
B = [4,5]
输出: 3

挑战

时间复杂度为O(log n)

算法1:最简单的办法就是把两个数组合并、排序,然后返回中位数即可,由于两个数组原本是有序的,因此可以用归并排序中的merge步骤合并两个数组。算法复杂度为O(m+n) 

class Solution {
public:
    double findMedianSortedArrays(vector<int> &A, vector<int> &B) {
        // write your code here
        vector<int> C;
        int i=0,j=0,m=A.size(),n=B.size();
        while(i<m&&j<n)
        {
            if(A[i]<=B[j])
            {
                C.push_back(A[i]);
                i++;
            }
          
            else
            {
                C.push_back(B[j]);
                j++;
            }
        }
        while(i<m)
        {
            C.push_back(A[i]);
            i++;
        }
        while(j<n)
        {
            C.push_back(B[j]);
            j++;
        }
        int k=C.size();
        if(k%2==0)
        {
            return (C[k/2]+C[k/2-1])/2.0;
        }
        else
        {
            return C[(k-1)/2];
        }
    }
};

算法2:对于一个长度为n的已排序数列a,若n为奇数,中位数为第(n/2+1)个数 , 若n为偶数,则中位数=[第(n/2)个数 + 第(n/2+1)个数] / 2 如果我们可以在两个数列中求出第K小的元素,便可以解决该问题

不妨设数列A元素个数为n,数列B元素个数为m,各自升序排序,求第k小元素

取A[k / 2] B[k / 2] 比较, 如果 A[k / 2] > B[k / 2] 那么,所求的元素必然不在B的前k / 2个元素中(证明反证法) 反之,必然不在A的前k / 2个元素中,于是我们可以将A或B数列的前k / 2元素删去,求剩下两个数列的 k - k / 2小元素,于是得到了数据规模变小的同类问题,递归解决

如果 k / 2 大于某数列个数,所求元素必然不在另一数列的前k / 2个元素中,同上操作就好。

class Solution {
public:
    double findKth(vector<int> &A, vector<int> &B, int A_st, int B_st, int k)
    {
        // 首先需要让数组1的长度小于或等于数组2的长度
        if (A.size() - A_st > B.size() - B_st) 
        {
            return findKth(B, A, B_st, A_st, k);
        }
        // 判断小的数组是否为空,为空的话,直接在另一个数组找第K个即可
        if (A.size() == A_st)
        {
            return B[B_st + k - 1];
        }
        // 当K = 1时,表示我们要找第一个元素,只要比较两个数组的第一个元素,返回较小的那个即可
        if (k == 1) {
            return min(A[A_st], B[B_st]);
        }
        int pa = min(A_st + k / 2, int(A.size())), pb = B_st + k - (pa -A_st);
        
        if (A[pa - 1] < B[pb - 1]) {
            return findKth(A, B, pa,B_st, k - pa + A_st);
        }
        else if (A[pa - 1] > B[pb - 1]) {
            return findKth(A, B, A_st, pb, k - pb + B_st);
        }
        else {
            return A[pa - 1];
        }
    }
    double findMedianSortedArrays(vector<int> &A, vector<int> &B) {
        // write your code here
        int sum = A.size() + B.size();
        double ret;
        
        if (sum %2!=0) 
        {
            ret = findKth(A, B, 0, 0, sum / 2 + 1);
        } 
        else 
        {
            ret = ((findKth(A, B, 0, 0, sum / 2)) +
                    findKth(A, B, 0, 0, sum / 2 + 1)) / 2.0;
        }
        return ret;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值