【递归 每次锁定一半】 4 寻找两个正序数组的中位数

题目

给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。
请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
nums1 = [1, 3]
nums2 = [2]
中位数为2
nums1 = [1, 2]
nums2 = [3, 4]
中位数为(2 + 3)/2 = 2.5

思路

如果要找第k小的数字,就循环每次排除掉第k/2的数字。
两个数字同时指向当前第k/2个数字,当前数字哪个小,那么该数组之前的序列被舍掉,指针移动到k减去舍掉元素的之后的新k值的一半位置。
解法三图示

代码

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    int len1 = nums1.length;
    int len2 = nums2.length;

    int left = (len1+len2+1)/2;
    int right = (len1+len2+2)/2;
    if(len1==0) return (nums2[left-1]+nums2[right-1])*0.5;
    if(len2==0) return (nums1[left-1]+nums1[right-1])*0.5;
    //奇数偶数两种情况,如果是奇数那么求出两个相等的值,如果是偶数则相加除2
    return (findMid(nums1,0,len1-1,nums2,0,len2-1,left)+findMid(nums1,0,len1-1,nums2,0,len2-1,right))*0.5;
}
public int findMid(int []nums1,int start1,int end1,int []nums2,int start2,int end2,int k){
    int len1 = end1-start1+1;
    int len2 = end2-start2+1;
    //当数组较短已经整个班排除掉时,直接计算剩余数组剩余元素的从start开始的第k小的元素
    if(len1==0){
        return nums2[start2+k-1];
    }
    if(len2==0){
        return nums1[start1+k-1];
    }
    //当只剩一个数时,直接比较两个数的最小值
    if (k == 1) return Math.min(nums1[start1], nums2[start2]);
    //每次应该比较第几个数字
    //当长度小于K/2时,i增加的长度就是数组长度,即将剩余数组并入。
    int i =start1+ Math.min(len1,k/2)-1;
    int j =start2+Math.min(len2,k/2)-1;
    if(nums1[i]>nums2[j]){
        return findMid(nums1,start1,end1,nums2,j+1,end2,k-(j-start2+1));
    }
    else{
        return findMid(nums1,i+1,end1,nums2,start2,end2,k-(i-start1+1));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值