Leetcode-Median of Two Sorted Arrays (java)

题目


给定两个排序过的数组,长度为m、n,找到两个数组的中位数,时间复杂度要求O(log(m+n))。

解答

该题的主要难点在于对时间复杂度的要求,若是没有要求,较为直观的解法是先将两个排序数组合并为一个数组,再计算中位数,显然时间复杂度为O(n+m),不能满足题目要求。观察该题的时间复杂度,有一个log存在,一般需要对半处理的情况时间复杂度里含有log,例如二分法。但是该题的解法很难想到。

leetcode上给了英文解释,将该问题转化为找第k大的数字,k = (m+n)/2。首先假设A,B两个数组的大小大于k/2,然后比较A[k/2-1]和B[k/2-1]两个元素的大小情况。

1.A[k/2-1]<B[k/2-1],说明将A、B数组合并后,A中前k/2个元素都小于第k大的数,可以将其舍去(假设A中前k/2个元素包含第k大的数,则合并A、B中前k/2个元素后,第k大的数不是第k个,因为第k个数为B[k/2-1],矛盾)。

2.A[k/2-1]>B[k/2-1],与第一种情况类似,舍去B中前k/2个元素。

3.A[k/2-1]=B[k/2-1],说明A[k/2-1]就是第k大的数字。

所以可以利用递归的方法不断比较两个数组中第k/2大的数,直到结束。递归结束条件有三个:

1.若A数组为空,直接返回B[k-1]。

2若k为1,返回A[start]和B[start]中较小的数。

3若A[k/2-1]=B[k/2-1],返回A[k/2-1]。

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2)
    {
        int len = nums1.length+nums2.length;
        if((len&1)!=0)
            return findKth(nums1,0,nums1.length-1,nums2,0,nums2.length-1,len/2+1);
        else 
            return (findKth(nums1,0,nums1.length-1,nums2,0,nums2.length-1,len/2)+findKth(nums1,0,nums1.length-1,nums2,0,nums2.length-1,len/2+1))/2.0;
    }
    
    public double findKth(int[]nums1,int start1,int end1,int[] nums2,int start2,int end2,int k)
    {
        int m = end1-start1+1;
        int n = end2-start2+1;
        if(m>n)
            return findKth(nums2,start2,end2,nums1,start1,end1,k);
        if(m==0)
            return nums2[k-1];
        if(k==1)
            return Math.min(nums1[start1],nums2[start2]);
        int partA = Math.min(k/2,m);
        int partB = k-partA;
        if(nums1[start1+partA-1]<nums2[start2+partB-1])
        {
            return findKth(nums1,start1+partA,end1,nums2,start2,end2,k-partA);
        }
        else if(nums1[start1+partA-1]>nums2[start2+partB-1])
        {
            return findKth(nums1,start1,end1,nums2,start2+partB,end2,k-partB);
        }
        else
            return nums1[start1+partA-1];
        
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值