Leetcode刷题日记 -- Median of Two Sorted Arrays

来源:互联网 发布:数组中和为n的组合 编辑:程序博客网 时间:2024/05/19 21:15

周日开始做这道题,然后想了1小时,智商捉急没有想到怎么做,思路无限接近,但是最后一个关键点没想通。然后搜了一下别人的作法。

这里借用一下zhanglei在他博客里写的c++的实现,讲的很简单明了。但是我跟他的实现还是有些小的差别。这题前几天的时候总会出边界条件的错误,这也是纠结到今天才写日记的原因。今天实在背不住用eclipse调试发现是自己粗心,借用别人算法但是没有根据自己的实际情况改好。主要的问题集中在数组的index上。

贴题:

There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

转载部分:

[解题思路]
O(n)的解法比较直观,直接merge两个数组,然后求中间值。而对于O(log(m+n))显然是用二分搜索了, 相当于“Kth element in 2 sorted array”的变形。如果(m+n)为奇数,那么找到“(m+n)/2+1 th element in 2 sorted array”即可。如果(m+n)为偶数,需要找到(m+n)/2 th 及(m+n)/2+1 th,然后求平均。

而对于“Kth element in 2 sorted array”, 如下图,两个中位数 A[m/2] 和 B[n/2], 可以将数组划分为四个部分。而丢弃哪一个部分取决于两个条件:1, (m/2 + n/2)?k;2,A[m/2] ? B[n/2];


如果 (m/2 + n/2) > k,那么意味着,当前中位数取高了,正确的中位数要么在 Section 1或者Section3中。如果A[m/2] > B[n/2], 意味着中位数肯定不可能在Section 2里面,那么新的搜索可以丢弃这个区间段了。同理可以推断出余下三种情况,如下所示:

If (m/2+n/2+1) > k && am/2 bn/2 , drop Section 2
If (m/2+n/2+1) > k && am/2 bn/2 , drop Section 4
If (m/2+n/2+1) k && am/2 > bn/2 ,  drop Section 3
If (m/2+n/2+1) k && am/2 bn/2 ,  drop Section 1


简单的说,就是或者丢弃最大中位数的右区间,或者丢弃最小中位数的左区间。


贴代码 我的代码中k是数组元素的index,而不是第k个元素

public class Solution {    public double findMedianSortedArrays(int A[], int B[]) {        int m = A.length;        int n = B.length;        if((m + n)%2 == 0){            return ((double)getMedian(A,0,m-1,B,0,n-1,(m + n)/2 - 1) + (double)getMedian(A,0,m-1,B,0,n-1,(m + n)/2))/2;        }else{            return (double)getMedian(A,0,m-1,B,0,n-1,(m + n)/2);        }    }        public int getMedian(int[] A, int as, int ae, int[]B, int bs, int be, int k){        if(as > ae){            return B[k + bs];        }        if(bs > be){            return A[k + as];        }if(k <= 0){            return A[as] < B[bs]?A[as]:B[bs];        }        int midA = (ae - as + 1)/2 + as;        int midB = (be - bs + 1)/2 + bs;        if(A[midA] > B[midB]){            if(k >= (midA - as + midB - bs + 1))return getMedian(A,as,ae,B,midB+1,be,k - midB + bs - 1 );             else return getMedian(A,as,midA-1,B,bs,be,k);        }else{            if(k >= (midA - as + midB - bs + 1))return getMedian(A,midA+1,ae,B,bs,be,k - midA + as - 1 );             else return getMedian(A,as,ae,B,bs,midB-1,k);        }    }}



注意的点:

1. K >= (midA - as + midB - bs + 1), 一定是大于等于,带等号,因为保证去掉的部分尽量是前面的部分即section1 和 section3,这样k不会超界。反例:A=[1] ,B = [1]。

2. 中位数取(ae-ae)/2 或者(ae-ae+1)/2都可以。


这道题的难度主要是在边界条件的考虑。算法倒是比较容易记住和理解。是leetcode里面最难的题之一。Mark之


0 0
原创粉丝点击