Leetcode4 Median of Two Sorted Arrays

这是一道Hard的题,确实是难诶,感觉就是道数学题,像高考数学求导的那道大题一样,各种情况和边界条件需要考虑,还需要推导。自己没写出来,

主要参考Solution: https://leetcode.com/problems/median-of-two-sorted-arrays 和discuss:https://leetcode.com/problems/median-of-two-sorted-arrays/discuss/2481/Share-my-O(log(min(mn))-solution-with-explanation

他们的思路是一样的,不过一个是java一个是python而已。

详细的可以去看原文,这里只整理思路。

首先是根据中位数的定义,将问题等价为了

      left_part          |        right_part
A[0], A[1], ..., A[i-1]  |  A[i], A[i+1], ..., A[m-1] B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]

用i,j去分割AB两个数组,如果上面的分割可以得到中位数,那么有

1) len(left_part) == len(right_part) or len(right_part)+1 (人为规定如果odd的话leftpart大一点,这个无所谓,leftpart大的话就从leftpart找结果就行)
2) max(left_part) <= min(right_part)

那么even: median = (max(left_part) + min(right_part))/2 ;odd: median=left_part[-1]

上面两条件等价:

 1) i+j = m-i+n-j or m-i+n-j+1

 2) A[i-1]<=B[j] and B[j-1]<=A[i]

其中对于1)我们可以约束m<=n,那么有 j = (m+n+1)//2-i 。于是:

 1)  j = (m+n+1)//2-i   s.t.m<=n

 2) A[i-1]<=B[j] and B[j-1]<=A[i]

在条件1)下,有了i我们就有了j,于是我们在[0,m]里对i进行二分查找。(为什么是左闭右闭呢,因为i其实是一个位置,而不是一个元素,比如i=0,代表在元素0之前分割,i=m,代表在元素m之前(元素m不存在,等价与元素m-1之后分割))

对于2)i=0时,A[i-1]不存在;类似的,j=0,i=m,j=n时,B[j-1],A[i],B[j]不存在,所以这个边界条件我们也要处理一下。

i=0时,说明我们对i的搜索已经进行完毕,A组数据都应该在rightpart,那么i就是我们要的i了,至于结果怎么样要看是odd还是even了;

i=m时,A组数据都应该在leftpart,那么i就是我们要的i了;

j类似。

所以,i什么时候小呢?

B[j-1]>A[i]&&j!=0&&i!=m

等价于 B[j-1]>A[i]&&j>0&&i<m

i什么时候大呢?

A[i-1]>B[j]&&i!=0&&j!=n

等价于 A[i-1]>B[j]&&i>0&&j<n

剩下的时候就是i合适了。

但是这时i=0,j=0,i=m,j=n这几个特殊情况会影响我们的公式,所以要特殊处理。

照这个思路写了一版,并不对,先放这儿吧。

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m=nums1.length,n=nums2.length;
        //ensure m<=n orelse j=(m+n+1)/2-i might be a negative interger ,that's not what we want
        if(m>n) {
            int[] temp=nums1;nums1=nums2;nums2=temp;
            int tempi = m;m=n;n=tempi;
        }
        if(m==0) {
            if(n%2==0) return (nums2[n/2-1]+nums2[n/2])/2.0;
            else return (double)nums2[n/2];
        }
        //i,j represents where we divide nums1,nums2 to two equivalent parts or len(left)==len(right)+1
        int i=0,j=(m+n+1)/2-i; 
        //binary search
        int pl=0,pr=m;
        while(pl<=pr) {
            i=(pl+pr)/2;
            j=(m+n+1)/2-i;
            int leftmax,rightmin;
            if(j>0&&i<m&&nums2[j-1]>nums1[i]) { //i is too small
                pl=(pl+pr)/2+1;
            }
            else if(i>0&&j<n&&nums1[i-1]>nums2[j]) {  //i is too big
                pr=(pl+pr)/2-1;
            }
            else { //i,j are what we want
                if(i==0) leftmax=nums2[j-1];
                else if(j==0) leftmax=nums1[i-1];
                else leftmax=Math.max(nums1[i-1],nums2[j-1]);
                if(i==m) rightmin=nums2[j];
                else if(j==n) rightmin=nums1[i];
                else rightmin = Math.max(nums1[i], nums2[j]);
                if((m+n)%2==0) return (leftmax+rightmin)/2.0;
                else return (double)leftmax;
            }
        }
        return 0.0;
    }
}
Wrong Answer
Input
[1,2]
[-1,3]
Output
2.0
Expected
1.5

猜你喜欢

转载自www.cnblogs.com/chason95/p/9969737.html
今日推荐