【leetcode】之Median of Two Sorted Arrays

本文探讨了一道经典算法题:寻找两个已排序数组的中位数,并给出了一个复杂度为O(log(m+n))的解决方案。通过巧妙地使用分治递归思想,避免了完全排序,从而大幅提高了算法效率。

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

问题描述:
There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

我的解题思路:
拿到这道题目,最简单的思路就是直接采用归并排序中的merge算法,就可以在O(m+n)的时间复杂度内完成排序,然后可以在O(1)的时间内找到第[(m+n)/2]大的数,但是题目要求的复杂度是O(log(m+n)),所以自然需要思考优化策略。

比较容易想到的优化策略是:不对整个数组进行排序,而是把目标锁定在寻找最小的[(m+n)/2]个数。可以设置两个指针,分别指向两个数组,然后进行遍历,直至找到[(m+n)/2]个数,这种做法的复杂度还是O(m+n),依然不符合要求。

然后就是思考如何做到O(log(m+n)),因为有log的存在,就自然可以往分治递归,二叉树(如最大最小堆),二分法上面去想。到这里为止,我的思路大体都是对的。但是下一步我的思路就出问题了。我尝试利用分治递归的思想,把原问题化成子问题,但是我一直在想着对两个数组直接取中值进行划分,然后再进行后续的操作。这种划分子问题的方法是行不通的。之后是看了参考资料

http://blog.youkuaiyun.com/yutianzuijin/article/details/11499917/
才想明白划分子问题的方法,具体的内容这份博客讲的很多好了,我就只贴一下程序:

class Solution  
{  
private:
    double findkth(vector<int>::iterator a,int m,
                vector<int>::iterator b,int n,
                int k)
    {
        if(m >  n)
            return findkth(b,n,a,m,k);
        if(m == 0)
            return b[k-1];
        if(k == 1)
            return min(*a,*b);

        int pa = min(k/2,m),pb = k - pa;
        if(*(a + pa - 1) < *(b + pb -1))
            return findkth(a+pa,m-pa,b,n,k-pa);
        else if(*(a + pa -1) > *(b + pb -1))
            return findkth(a,m,b+pb,n-pb,k-pb);
        else
            return *(a+pa-1);
    }
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        vector<int>::iterator a = nums1.begin();
        vector<int>::iterator b = nums2.begin();
        int total = nums1.size() + nums2.size();

        // judge the total num of two arrays is odd or even
        if(total & 0x1)
            return findkth(a,nums1.size(),
                           b,nums2.size(),
                           total/2+1);
        else
            return (findkth(a,nums1.size(),
                           b,nums2.size(),
                           total/2) +
                    findkth(a,nums1.size(),
                            b,nums2.size(),
                            total/2 + 1))/2;
    }
};  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值