力扣 4. 寻找两个正序数组的中位数 二分

181 篇文章 1 订阅
54 篇文章 1 订阅

https://leetcode-cn.com/problems/median-of-two-sorted-arrays/
在这里插入图片描述
思路一:双指针 O ( n ) O(n) O(n)合并两个有序数组。

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
    int n=nums1.size();
    int m=nums2.size();
    int need=((n+m)>>1)+1,l=0,r=0;
    bool odd=(n+m)&1;
    vector<int> vec(need);
    while(need)
    {
        if(l==n||(r!=m&&nums1[l]>nums2[r]))
            vec[--need]=nums2[r++];
        else
            vec[--need]=nums1[l++];
    }
    return odd?vec[0]:(vec[0]+vec[1])/2.0;
    }
};

思路二:二分。假设要找到两个序列内第 k k k小的元素,可以比较 a [ k / 2 − 1 ] a[k/2-1] a[k/21] b [ k / 2 − 1 ] b[k/2-1] b[k/21]

  • 前者小于后者,那么最多有k-1个元素小于或等于a [ k / 2 − 1 ] [k /2-1] [k/21],因此可以排除 a [ 0 … k / 2 − 1 ] a[0…k/2-1] a[0k/21]
  • 后者小于前者,同理可以排除 b [ 0 … k / 2 − 1 ] b[0…k/2-1] b[0k/21]
  • 前者等于后者,可以归入上述两种情况的任意一种处理。

每次可以排除一半的元素,因此这个算法的复杂度是 l o g log log的。不过还有一些细节需要考虑,比如到达每个数组的末尾,或者 k = 1 k=1 k=1

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int n=nums1.size(),m=nums2.size(),mid=((n+m)>>1)+1;
        if((n+m)&1)
            return getkth_element(nums1,nums2,0,0,mid);
        else
            return (getkth_element(nums1,nums2,0,0,mid-1)+getkth_element(nums1,nums2,0,0,mid))/2.0;
    }

    int getkth_element(vector<int> &a,vector<int> &b,int idx1,int idx2,int k)
    {
        int n=a.size(),m=b.size();
        if(idx1==n)
            return b[idx2+k-1];
        else if(idx2==m)
            return a[idx1+k-1];
        else if(k==1)
            return min(a[idx1],b[idx2]);
        int k2=k>>1;
        int nidx1=min(idx1+k2-1,n-1),nidx2=min(idx2+k2-1,m-1);
        if(a[nidx1]<=b[nidx2])
            return getkth_element(a,b,nidx1+1,idx2,k-nidx1-1+idx1);
        else 
            return getkth_element(a,b,idx1,nidx2+1,k-nidx2-1+idx2);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值