LeetCode 4. Median of Two Sorted Arrays|分治思想

算法题目

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)).

leetcode原题链接

算法分析

这个题目要求实际上挺严格的,上来就直接规定时间复杂度为O(log(m+n)),所以我们必须要好好利用起已经排好序的这个条件。看到log的时间复杂度,我们不难想到要用分治的思想。但一开始的时候我太过于纠结中值,而不能在解答全局来看,导致进入了死胡同。至于这个分治怎么使用,我一开始也没想到,后来查了一下解法,发现只要我们不要把他想成找中值,而要想成找第k小的数(在本题中k= (m+n)/2),这样就很容易进行递归运算。
比如一开始是在第k大的数,那么比较A[k/2-1]与B[K/2-1],如果B[K/2-1]>A[k/2-1],那么就证明A[0]~A[k/2-1]之间的数都应该比这两个数组的中值要小,所以就可以剔除这k/2个数,这么一来,问题从找到第k小的数就转换为找第k/2小的数了。依次类推,找到k=0时,就只需要比较A’[0]和B’[0]哪个数较小就可以找到所需要的数了。
分析一下时间复杂度是O(logk)=O(log(m+n)/2)=O(log(m+n)符合题目要求。
我写的代码中没有用递归的方法,所以代码比较杂乱,但是主要思想还是一样的。


double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
    int right1;
    int right2;
    if(!nums1.empty())
    right1 = nums1.size()-1;
    else right1 = -1;
    int left1 = 0;
    if(!nums2.empty())
    right2 = nums2.size()-1;
    else right2 = -1;
    int left2 = 0; 
    int tot_length =  right1+right2+2;
    bool isodd= true;
    if(tot_length%2==0) isodd= false;
    int k = (tot_length-1)/2;//找到合并之后下标为k的数

    while(k>0&&left1<=right1&&left2<=right2){
        int tem =max(k/2-1,0); //每次循环可以剔除一半的k的数量
        //避免越界 
        if(left1+tem>=right1){
            tem = right1-left1;
        }
        if(left2+tem>=right2){
            tem = right2-left2;
        }

        if(nums1[left1+tem]>nums2[left2+tem]){
            //剔除nums2的较小的
            left2+=tem+1; 
        } 
        else {
            left1+=tem+1;
        }
        k-=tem+1;
    }


    if(left1>right1) {
    if(isodd) return nums2[left2+k];
    else return (double)(nums2[left2+k]+nums2[left2+k+1])/2;
    }

    if(left2>right2) {
    if(isodd) return nums1[left1+k];
    else return (double)(nums1[left1+k]+nums1[left1+k+1])/2;
    }

    if(isodd){
    if(nums1[left1]>nums2[left2]) return nums2[left2];
    else return nums1[left1];
    }

    else{
        int t;
        if(nums1[left1]>nums2[left2]) {
            t= nums2[left2];
            left2++;}
        else {t=nums1[left1];left1++;}

        if(left1>right1) return (double)(t+nums2[left2])/2;
        if(left2>right2) return (double)(t+nums1[left1])/2;     

        if(nums1[left1]>nums2[left2]) 
             return (double)(t+nums2[left2])/2;

        else return (double)(t+nums1[left1])/2;     

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值