【LeetCode】4. 寻找两个有序数组的中位数(特殊的二分法)

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

关键点

  • 复杂度为O(log(m + n))
  • 有序数组

思路

  • 将两个数组拼成一个数组,再求中位数。
    从复杂度上分析,如果是一个长度为m + n的有序数组,则查找中位数的复杂度为O(1),直接取得length / 2处即为答案。而将两个有序数组拼成一个有序数组的复杂度为O(m + n),已经超过了题目所要求的复杂度。不行
  • 从log处思考,log级别的算法可以考虑二分法。
    两个数组如何进行二分?
    分析最终的答案与两个数组的中位数的关系:假设K = (n + m) / 2,即为中位数的序号,找到两个数组的第K大的数即找到答案。
    我们给A和B数组每人一个K / 2个数字的机会。
           Ka
A:----------|---------------
       1            2
       
           Kb
B:----------|-------------------------------
      3                    4

假设上面是A与B两个有序数组(从小到大),竖线处为Ka = A[K / 2]Kb = B[K / 2]
这四段的长度分别为L1, L2, L3, L4

比较Ka与Kb,若Ka > Kb
那么K一定不会落在小于Kb的这一段,也就是L3上(自己体会)。
那么也就是在L1 + L2 + L4中查找第K - L3个数。
每次都可以排除K / 2段,K = (n + m) / 2,所以总体复杂度为O(log(m + n))

代码

double min(double a,double b){
    if(a>b)return b;
    return a;
}
double calKth(int a[],int n,int b[],int m,int k){
    if(n==0)
        return b[k-1];
    else if(m==0)
        return a[k-1];
    if(k==1)
        return min(a[0],b[0]);
    int ma=min(k/2,n),mb=min(k/2,m);
    if(a[ma-1]>b[mb-1]){
        return calKth(a,n,b+mb,m-mb,k-mb);
    }
    return calKth(a+ma,n-ma,b,m,k-ma);
}
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
    if((nums1Size+nums2Size)%2){
        return calKth(nums1,nums1Size,nums2,nums2Size,(nums1Size+nums2Size+1)/2);
    }
    int k1=(nums1Size+nums2Size)/2,k2=k1+1;
    return (calKth(nums1,nums1Size,nums2,nums2Size,k1)+calKth(nums1,nums1Size,nums2,nums2Size,k2))/2.0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值