题目描述
有两个大小分别为m和n的有序数组A和B。请找出这两个数组的中位数。你需要给出时间复杂度在O(log (m+n))以内的算法。
思路分析
两个大小分别为m和n的有序数组,我们要找出它们的中位数,而且要求时间复杂度是对数级别的,那么我们自然而然地就会想到二分查找算法,可是要怎么进行呢?寻找这两个数组的中位数相当于在数组A和B中找到中间元素,如果数组元素总数是奇数那么就是最中间的那个元素((m+n)/2+1),如果是偶数那么就是最中间的两个元素((m+n)/2、(m+n)/2+1)。这样问题就转化成给定两个有序数组,求第k小元素了。
接下来就处理转化来的问题,在数组A中找到第k/2小元素a,在数组B中找到第k/2小元素b,如果a和b相等,那么第k小元素就是a或者b了,如果a小于b,那么总体的第k小元素不可能在a的第k/2小元素之前,那么就可以将其舍弃了,反之如果a大于b,也就可以舍弃b的第k/2小之前的元素了。
当然在实际代码中,数组A和数组B的元素个数可能小于k/2,我们就令其为pa=min(k/2,m or n),另外一个数组就是第pb=k-pa小元素了。

    double findMedianSortedArrays(int A[], int m, int B[], int n) 
    {
        int total=m+n; //两个数组的元素总个数
        if((total&0x1)) //奇数个,那么中间元素就是第total/2+1小元素了
            return findKth(A, m, B, n, total/2+1);
        else
            return (findKth(A,m,B,n,total/2)+findKth(A, m, B, n, total/2+1))/2;
    }
    //在数组A和数组B整体中寻找第k小数字
    double findKth(int A[],int m,int B[],int n,int k)
    {
        if(m>n)
            return findKth(B, n, A, m, k); //让元素少的放在前面,方便处理
        if(m==0)
            return B[k-1]; //如果元素少的数组为空,那么就返回另一个数组的第k小元素即可
        if(k==1) //如果求第1小元素
            return min(A[0],B[0]);
        int pa=min(k/2,m),pb=k-pa;
        if(A[pa-1]<B[pb-1])
            return findKth(A+pa, m-pa, B, n, k-pa);
        else if(A[pa-1]>B[pb-1])
            return findKth(A, m, B+pb, n-pb, k-pb);
        else
            return A[pa-1];
    }