leetcode 4. 寻找两个有序数组的中位数

 

 leetcode 4. 寻找两个有序数组的中位数

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

参考了一个大佬的视频,思路总结如下,基于大佬的代码,考虑了一下拓展到n个数组找第k个数的方法,也就是k/2变成k/n。

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        /*对每个数组设置各设置一个从左向右移动的指针left1和left2。
        * 把找2个有序数组中位数的问题转化为从当前指针开始找第k个数的问题。
        * 那么,可以通过递归查找第k个数。核心思想就是每次判断每个数组,在当前对应指针下从左向右移k/2有没有超过数组长度。
        * 如果没有超过哪个数组长度,就在哪个数组上偏移。
        * 这里要证明的一点是,每次反复偏移某一个数组k/2是否可行?
        * 如果有一个数组长度很小,比如nums1长度为100,nums2长度为10,找中位数第k=55和56的平均数,
        * 可以保证的是,无论nums2中的数大小,如果nums1当前第k/2个数比num2当前第k/2数小,nums1中前k/2个数一定在总共前k个数中,因为k/2+nums2.length<k
        * 这个可以多种方法证明,我们讨论一下,nums1当前第k/2个数要么在前k个数中、要么不在,nums2也是一样,我们只要判断其中一个一定在,做偏移就好。
        * 给定nums1[left1+k/2-1] < nums2[left2+k/2-1],如果nums2的在前k个中,nums1的一定在;如果nums2的不在前k个中,那么nums2中占有前k个数就少于k/2个,即nums1中占有前k个数大于k/2个数,所以nums1[left2+k/2-1]一定在总共前k个中,证毕。
        * 拓展:如果共有n个数组,nums1,nums2,...,numsn,比较起来也是类似的,分类讨论前k/n个数
        * */
        int sum = nums1.length+nums2.length;
        if (sum%2==0){
            return (findKthNum(nums1,0,nums2,0,sum/2)+findKthNum(nums1,0,nums2,0,sum/2+1))/2.0;
        }else return (findKthNum(nums1, 0,nums2,0,sum/2+1));
    }
    // 找第k个数
    public double findKthNum(int[] nums1, int left1, int[] nums2, int left2, int k) {
        //如果left1>nums1的长度,直接返回在nums2中第k个数
        //如果left2>nums2的长度,直接返回在nums1中第k个数
        //如果k==1,找nums1和nums2中当前指针中最小的一个数
        //否则比较nums1和nums2的两个指针left1和left2,如果找第k个数时,left1+k/2超过nums1的长度而left2+k/2没超过nums2的长度,就在nums2中找k/2个数,反之亦然(不考虑k大于sum/2的情况)
        if(left1>=nums1.length) return nums2[left2+k-1];
        if(left2>=nums2.length) return nums1[left1+k-1];
        if(k==1) return Math.min(nums1[left1],nums2[left2]);
        int mid1 = left1+k/2-1 < nums1.length ? nums1[left1+k/2-1] : Integer.MAX_VALUE;
        int mid2 = left2+k/2-1 < nums2.length ? nums2[left2+k/2-1] : Integer.MAX_VALUE;
        if(mid1<=mid2){
            return findKthNum(nums1, left1+k/2, nums2, left2, k-k/2);
        }
        return findKthNum(nums1, left1, nums2, left2+k/2, k-k/2);
    }

大佬的思路真的牛逼

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值