【LeetCode系列】有序数组的中位数 Median of Two Sorted Arrays

问题描述: 

解决方案: 

因为题目中给出的是已排序的数组,因此将问题转化为求第 k 小的数,当两个数组大小之和为奇数时,找第 \frac{m+n}{2} + 1小的数;当两数组之和为偶数时,找中间两个数之和除以2即可,中间两个数分别为第\frac{m+n}{2}\frac{m+n}{2}+1小的数。

假设找第k小的数需要在数组A中找p次,在数组B中找q次,则 p + q = k。k已知而p和q未知,因此目的就是通过二分k找到p。

A[start1 + p - 1]代表的含义是指数组A“前进”了p步,对应于数组B需要“前进”q步。

①若A[start1 + p - 1] = B[start2 + q - 1],意味着已经找到,第k个数 kth = A[start1 + p - 1] = B[start2 + q -1]。因为A和B都是有序的,因此从A[start1]到A[start1 + p - 1](共p - 1 + 1个数)、B[start2]到B[start2 + q - 1](共q - 1 + 1个数)也是有序的,如果将这两个子数组合并成一个数组则总共有 p - 1 + q - 1 + 2= k个数,而其中最大的数就是A[start1 + p - 1] = B[start2 + q - 1],即第k小的数(注意每个数组都是从小到大排序的,并不需要关心合并后的内部顺序)。

②若A[start1 + p - 1] < B[start2 + q - 1],意味着数组A中A[start1 + p - 1]之前的数字全都小于B[start2 + q - 1](因为数组A是从小到大排序的),因此第k小的数一定不会在数组A的前p个数中,因此我们可以把它舍弃以后进行递归操作,但递归时因为我们舍弃了前面的p个数,因此下一步就是找第 k - p小的数了。

③若A[start1 + p - 1] > B[start2 + q - 1],与上面情况类似,舍弃数组B的前q个元素,递归找第 k - q 小的数。

 

class Solution {
    public double findMedianSortedArrays(int[] A, int[] B) {
        int m = A.length;
        int n = B.length;
        int total = m + n;
        if((total % 2) == 1){
            return findKthNumber(A, m, 0, B, n, 0, total / 2 + 1);    //找到第total/2+1小的数
        }else{
            return (findKthNumber(A, m, 0, B, n, 0, total / 2) + findKthNumber(A, m, 0, B, n, 0, total / 2 + 1)) / 2;
        }
    }
    
    public double findKthNumber(int[] A, int m, int start1, int[] B, int n, int start2, int k){
        //一定注意这三个if的顺序
        if(m > n){    //保证A的长度一定小于B
            return findKthNumber(B, n, start2, A, m, start1, k);
        }
        if(m == 0){    //如果一个数组长度为0,则只要直接返回另一个数组的第k个元素即可
            return B[start2 + k - 1];
        }
        if(k == 1){    //返回第1小的数只要比较当前A和B中最小的即可
            return Math.min(A[start1], B[start2]);
        }
        //第k小的数在数组A中找了p次,在数组B中找了q次,p + q = k
        //二分:实际上是二分k找p
        int p = Math.min(k/2, m);    //若p > m会越界, 因此返回两者中的小值
        int q = k -p;
        if(A[start1 + p - 1] == B[start2 + q - 1]){    //说明已找到
            return A[start1 + p - 1];
        }else if(A[start1 + p - 1] < B[start2 + q - 1]){
            return findKthNumber(A, m - p, start1 + p, B, n, start2, k - p);
        }else{
            return findKthNumber(A, m, start1, B, n - q, start2 + q, k - q);
        }
    }
}

参考:

https://www.jianshu.com/p/9bd57fd52062

https://blog.csdn.net/yutianzuijin/article/details/11499917

https://leetcode.com/problems/median-of-two-sorted-arrays/solution/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值