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;
}
}
[-1,3]

浙公网安备 33010602011771号