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(m+n)的解法,就是先Merge两个数组,然后返回中位数,用到了归并排序里面Merge的过程。要想得到O(log(m+n))的解法,需要用到分治法。寻找A和B数组的中位数,如果(m+n)为奇数,我们就是要寻找A和B中的第(m+n)/2+1的数(注意是下取整),如果(m+n)是偶数,我们是要寻找第(m+n)/2 和 (m+n)/2+1数然后取平均。所以,解决这个问题我们只需要解决求第k大的问题,这是一个经典问题。采用分治法求解第k大的O(logn)的算法思路如下: 我们比较A[k/2]和B[k - k/2](就是让待比较元素之前含比较元素一共有k个元素,k - k/2这么写可以处理奇数的情况),如果A[k/2] = B[k - k/2],那么A[k/2]就是第k大数。如果A[k/2] > B[k - k/2],那么第k大元素一定在A"左侧"和B”右侧“的区间内,注意这里左右是相对于中间那个比较元素而言的。所以我们更新A的right boundary和B的left boundary(类似二分查找),同时由于我们拿掉了B左侧这里一共posB = (k - k/2)个数,这些数是比目标数小的数,所以第k大变成了k-posB大数,更新左右边界和k后我们可以递归调用findK函数;当A[k/2] < B[k - k/2]的情况类似可以推理递归的方法。最后一直递归到k=1或者比较短的数组长度为0,求第k大就非常容易一目了然了。具体实现中还要注意保证A长度始终小于B,否则就做交换,同时对于A数组如果长度已经小于k/2,就应该把A最后一个元素拿来做比较,所以每次计算posA=Math.min(k/2,m),posB = k - posA。求第K大的O(logn)算法是分治法的一个经典应用,要熟练掌握灵活应用。
AC Code
public class Solution {
public double findMedianSortedArrays(int A[], int B[]) {
int m = A.length;
int n = B.length;
if((m + n) % 2 == 0){
return (findKth(A, B, 0, m - 1, 0, n - 1, (m + n) / 2) + findKth(A, B, 0, m - 1, 0, n - 1, (m + n) / 2 + 1)) / 2.0;
} else {
return findKth(A, B, 0, m - 1, 0, n - 1, (m + n) / 2 + 1);
}
}
public int findKth(int A[], int B[], int Al, int Ar, int Bl, int Br, int k){//find the Kth element in the the merged array from A and B
int m = Ar - Al + 1;
int n = Br - Bl + 1;
if(m > n){//let the length of A is always shorter than the length of B
return findKth(B, A, Bl, Br, Al, Ar, k);
}
if(m == 0){
return B[Bl + k - 1];
}
if(k == 1){
return Math.min(A[Al], B[Bl]);
}
int posA = Math.min(k / 2, m);
int posB = k - posA;
if(A[Al + posA - 1] < B[Bl + posB - 1]) {//In this case, find the (k-posA)th element in the right of A and left of B
return findKth(A, B, Al + posA, Ar, Bl, Bl + posB -1, k - posA);
} else if(A[Al + posA - 1] > B[Bl + posB - 1]){//In this case, find the (k - posB)th element in the right of B and left of A
return findKth(A, B, Al, Al + posA - 1, Bl + posB, Br, k - posB);
} else {
return A[Al + posA - 1];//In this case, both A[Al + posA - 1] and B[Bl + posB - 1] are the kth element we want to find
}
}
}
参考了http://codeganker.blogspot.com/2014/02/median-of-two-sorted-arrays-leetcode.html