力扣 4. 寻找两个有序数组的中位数 递归+二分

54 篇文章 1 订阅
20 篇文章 0 订阅

https://leetcode-cn.com/problems/median-of-two-sorted-arrays/
在这里插入图片描述

思路:这个复杂度限定还是挺有意思的。假设 g e t k t h ( k ) getkth(k) getkth(k)可以求出数组 a a a和数组 b b b后并之后的第 k k k个数,设数组 a 、 b a、b ab的长度分别为 n 1 、 n 2 n_1、n_2 n1n2,设 k 1 = ( n 1 + n 2 + 1 ) / 2 , k 2 = ( n 1 + n 2 + 2 ) / 2 k_1=(n_1+n_2+1)/2,k_2=(n_1+n_2+2)/2 k1=(n1+n2+1)/2,k2=(n1+n2+2)/2,那么数组 a 、 b a、b ab的中位数就等于 ( g e t k t h ( k 1 ) + g e t k t h ( k 2 ) ) / 2.0 (getkth(k_1)+getkth(k_2))/2.0 (getkth(k1)+getkth(k2))/2.0。这个比较简单,大家举几个例子就能推出来。现在我们考虑怎么实现这个 g e t k t h getkth getkth函数。我们可以设 k k = k / 2 kk=k/2 kk=k/2,那么通过比较 a [ k k ] a[kk] a[kk] b [ k k ] b[kk] b[kk]的大小,就可以筛去一部分不合题意的数字。假设 a [ k k ] > = b [ k k ] a[kk]>=b[kk] a[kk]>=b[kk] a a a数组中 < = a [ k k ] <=a[kk] <=a[kk]的数共有 k k − 1 kk-1 kk1个, b b b数组中 < = b [ k k ] <=b[kk] <=b[kk]的数共有 k k − 1 kk-1 kk1个,就算 b [ k k ] > = a [ k k − 1 ] b[kk]>=a[kk-1] b[kk]>=a[kk1],那么小于 b [ k k ] b[kk] b[kk]的数最多只有 2 ∗ k k − 2 2*kk-2 2kk2个,也就是说 b [ k k ] b[kk] b[kk]最大也不过是第 k − 1 k-1 k1大的数,由此我们可以看出 b [ 0 … k k ] b[0…kk] b[0kk]均不是符合题意的解,因此可以把这部分数筛去,问题转换成求两个新数组的第 k − ( k k + 1 ) k-(kk+1) k(kk+1)大的数。那么递归进行这个过程,就可以求得解。为了方便起见,我们在函数中新增 4 4 4个参数 b e g 1 , e n d 1 , b e g 2 , e n d 2 beg_1,end_1,beg_2,end_2 beg1,end1,beg2,end2用来限制 a 、 b a、b ab的范围,这样可以使得筛去操作容易实现。递归的出口就是 b e g 1 = e n d 1 beg_1=end_1 beg1=end1 b e g 2 = e n d 2 beg_2=end_2 beg2=end2 k = 1 k=1 k=1。同时考虑到某个数组的实际个数可能小于 k k kk kk,在限定范围的时候需要注意。

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int n1=nums1.size();
        int n2=nums2.size();
        int k1=(n1+n2+1)>>1;
        int k2=(n1+n2+2)>>1;
        return (getkth(nums1,0,n1,nums2,0,n2,k1)+getkth(nums1,0,n1,nums2,0,n2,k2))/2.0;
    }

    int getkth(vector<int>& nums1,int beg1,int end1,vector<int>& nums2,int beg2,int end2,int k){
        int len1=end1-beg1;
        int len2=end2-beg2;
        if(len1==0)
            return nums2[beg2+k-1];
        if(len2==0)
            return nums1[beg1+k-1];
        if(k==1)
            return min(nums1[beg1],nums2[beg2]);
        int id1=beg1+min(len1,k>>1)-1;
        int id2=beg2+min(len2,k>>1)-1;
        if(nums1[id1]>=nums2[id2])
            return getkth(nums1,beg1,end1,nums2,id2+1,end2,k-(id2-beg2+1));
        else
            return getkth(nums1,id1+1,end1,nums2,beg2,end2,k-(id1-beg1+1));
    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值