LeetCode 之 Median of Two Sorted Arrays

原题: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];    
        }
        
        
    }
};






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值