LeetCode4. Median of Two Sorted Arrays

题目链接:https://leetcode.com/problems/median-of-two-sorted-arrays/

给出两个有序数组,求得两个数组的中位数。时间复杂度要log(n+m)。

题意简单,但属实有些不好想。有序,时间复杂度要log。很容易想到二分。

先考虑偶数的情况。数组可以分成两个部分。

        left                    right
A[0],A[1],……A[i-1],  |  A[i],A[i+1],……A[n-1]
B[0],B[1],……B[j-1],  |  B[j],B[j+1],……B[m-1]

两个部分要满足以下条件:

  1. 左右个数left=right
  2. left的最大值要小于等于right的最小值。即:A[i-1]<=B[j]且B[j-1]<=A[i]

那么中位数为(max(A[i-1],B[j-1])+min(A[i],B[j]))/2。

该题的难点在于如何使用二分求得两个数组的i,j位置。

我们可以寻找i,j之间的关系。因为左右两边个数相等,所以:

i + j = n - i + m - j

i + j = (n + m) / 2 

j = (n + m ) / 2 - i;

这里要注意考虑j的取值

j不能为负数,其中i的取值为[0,n]。

所以不等式要满足 :

(n+m)/ 2 >= n,即 m>=n。

再考虑奇数的情况,奇数情况是左边的个数比右边的个数多一个,所以第一个条件变为

left = right + 1

而此时的中位数为:max(A[i-1],B[j-1])

i,j之间的关系变为:

i + j = n - i + m - j + 1

j = (n + m + 1) / 2 - i;

但是因为是int的计算,所以j = (n + m + 1) / 2 - i的情况包含了j = (n + m ) / 2 - i;的情况。所以我们使用j = (n + m + 1 ) / 2 - i;计算即可

所以使用二分的方法求 i ,然后通过公式求得 j。

当此时的 i ,j 满足 A[i-1]<=B[j]且B[j-1]<=A[i],即可求得其中位数。

但是到目前为止我们没有考虑i,j是边界和数组为空的情况。比如:

        left                    right
A[0],A[1],……A[n-1],  |  A[i]                   //注意此时A[i]并不存在,只是为了说明。
B[0],B[1],……B[j-1],  |  B[j],B[j+1],……B[m-1]


        left                    right
            A[i-1]   |  A[0],A[1],……A[n-1],    //注意此时A[i-1]并不存在,只是为了说明。
B[0],B[1],……B[j-1],  |  B[j],B[j+1],……B[m-1]

        left                    right
                     |                         //注意此时A不存在,只是为了说明。
B[0],B[1],……B[j-1],  |  B[j],B[j+1],……B[m-1]

当i,j是边界情况时,此时的我们只需要满足 A[i-1]<=B[j]或B[j-1]<=A[i]或者这个条件没有存在必要。

代码如下:

class Solution {
public:
    double findMedianSortedArrays(vector<int>& A, vector<int>& B) {
        int lena = A.size();
        int lenb = B.size();
        if(lena>lenb)
            return findMedianSortedArrays(B,A);
        int l=0,r=lena;
        int t = (lena+lenb+1)/2;
        double ans=-1;
        while(l<=r){
            int i=(l+r)>>1;
            int j=t-i;
            // printf("%d %d\n",i,j);
            if(i<r&&A[i]<B[j-1]){
                l+=1;
            }
            else if(i>l&&A[i-1]>B[j]){
                r-=1;
            }
            else{
                double maxl;
                if(i==0){
                    maxl=B[j-1];
                }
                else if(j==0){
                    maxl=A[i-1];
                }
                else{
                    maxl=max(A[i-1],B[j-1]);
                }
                if((lena+lenb)%2){
                    ans = maxl;
                    break;
                }
                
                double minr;
                if(i==lena){
                    minr=B[j];
                }
                else if(j==lenb)
                {
                    minr=A[i];
                }
                else
                {
                    minr=min(A[i],B[j]);
                }
                ans = (maxl+minr)/2;
                //printf("%d %d\n",maxl,minr);
                break;
            }
        }
        return ans;
    }
};

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值