您的位置:首页 > 其它

LeetCode 之 Median of Two Sorted Arrays

2013-12-01 03:24 369 查看
原题: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)).

这个题是求两个有序数组的中间数,其实这个中间数,如果是奇数,就是中间的那个数,如果是偶数,就是中间的两个数的和的平均值。

这个题有个关键,就是利用二分查找。。。。

如何在两个有序数组中利用二分查找,我用一个实例来进行讲解(在两个有序数组中找第k个元素,k一定小于两个数组的size()的和)数组A m个元素 ; 数组B n个元素 (先假设m < n):

1 分别找数组A的第k/2(pa)个元素(这里假设k/2 <= m),比较两个数组B的第k-pa(pb)个元素,如果A[pa]
< B[pb] ,那么第k个元素一定在A[pa+1] - A[last] 和B[1] - B[pb] 这几个元素中,如图1,为啥?数组A第1-pa和数组B第1-pb共k个元素,则图中两个相等之间的元素之前的所有元素的个数之和小于K,则数组A的前pa个元素一定小于第k个元素。



图1

2 知道了第k个元素在上述区间后,如果找第k个元素?

先分析一下上述的动作造成的结果。。。

第k个元素在数组A的pa位置以后,在数组B的pa位置以前,这就造成了一个后果,数组A的前pa个元素一定小于第k个元素。所以可以在数组A的pa-last和数组B的1-pb中找第k-pa个元素。

所以每进行一次1,就可以找到pa个比k小的数,所以相当于二分查找,下次就在这个区间中直接找第k-pa个元素就行。然后把数组A的起始位置移动到pa位置的下一个,数组B的大小缩小到pb处。

所以每次就进行1操作,每次都进行k-pa的操作,直到变成k=1(即找第1个元素),进行步骤3。

3 当k为1时,即从数组A和数组B中找第1个元素,就找两个数组的第一个元素中较小的就行。

4 上述的所有操作有一个盲点,就是如果k/2 > m ,举个例子:

A 1

B 2 3 4 5

这个例子就是如此,k/2是2,比A的size还要大,如何处理,就把pa指向这个数组的最后一个(即min(k/2 , m) ),pb=k-pa,如图2 ,如果A[pa] < B[pb] ,则第k个元素一定在数组B的1-pb中。而且数组A的所有元素都小于第k个元素,那么只需要在数组B中找第k-pa个元素就行了,这与步骤12是一样的。



图2

5 上述的情况都是考虑的数组A的第pa个元素大于B的第pb个元素,如果相反的情况呢?

则第k个元素一定在数组A的第1-pa之间和数组B的第pb-last之间的元素。下一次进行的操作和12一样。如图3



图3

6 该情况的返回情况除了当k为1时,还有一种情况,就是当A[pa] == B[pb],说明数组B的第pb个元素的两个数组的第k个元素。如图4



图4

代码(192ms):

class Solution {
public:
double findMedianSortedArrays(int A[], int m, int B[], int n) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
int sum = m+n;
//double result;
if(sum%2 == 0){
return  (findMedian(A,m,B,n,sum/2) + findMedian(A,m,B,n,sum/2+1) )/2 ;

}
else {
return findMedian(A,m,B,n,sum/2+1) ;
}

}

double findMedian(int A[] , int m , int B[] , int n , int k){

if(m>n) return findMedian(B , n , A , m , k);

if(m == 0) return B[k-1];
if(n == 0) return A[k-1];

if(k==1) return min(A[0],B[0]);

//两个数组都不为空
int pa = min(k/2,m);
int pb = min (k - pa , n);
if(A[pa-1] < B[pb-1]) {
return findMedian(A+pa,m-pa,B,pb,k-pa);
}
else if(A[pa-1] > B[pb-1]){
return findMedian(A,pa,B+pb,n-pb,k-pb);
}
else{
return B[pb-1];
}

}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: