LeetCode_Median of Two Sorted Arrays

一.题目

Median of Two Sorted Arrays

   Total Accepted: 38450  Total Submissions: 216286 My Submissions

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)).

Show Tags
Have you met this question in a real interview?  
Yes
 
No

Discuss




二.解题技巧

    这道题如果直接按照普通寻找第k小的算法来做的话,也是可以完成的,但是时间复杂度为O(logn),因为按照这种方法,是没有利用到两个数组已经排序了这一条件。考虑到这两个数组已经排好序了,因此,可以考虑利用二分搜索来进行。
    寻找中位数可以分成两个情况考虑,如果原来两个数组的个数的和k为奇数的话,那么就是寻找k/2+1小的数,如果k为偶数的话,就是寻找第k/2小的数和第k/2+1小的数的和,然后除以2。
    无论上面的哪种情况,都是要实现在两个已经排好序的数组中寻找第k小的数的问题。由于这两个数组都是已经排好序列的,因此,可以考虑首先比较数组A(有m个元素)和数组B(有n个元素)中的第k/2的位置的数的大小,这个时候有三种情况发生:
1.如果A[k/2-1] == B[k/2 -1]的话,那么就第k小的数就为A[k/2 -1]或者B[k/2-1]了; 
2.如果A[k/2-1]>B[k/2-1]的话,那么第k小的数只能出现在数组A的[0, k - 2]的位置或者B[k-1, n],这个可以通过画出数轴得到;此时,可以将问题转化为求解已经排好序的小数组A[0, k-1]和B[k-1, n]中第(k - k/2)小的数,递归调用就可以实现。
3.如果A[k/2-1]<B[k/2-1]的话,那么第k小的数只能出现在数组A的[k-1, m]的位置或者B[0, k-2];此时,可以将问题转化为求解已经排好序的小数组A[k-1, m]和B[0, k-2]中第(k - k/2)小的数,递归调用就可以实现。


   有了上面的解决方法,接下来就需要考虑边界条件了,主要的边界条件有:
1.如果数组A为空或者数组B为空,则返回A[k-1]或B[k-1];
2.如果k==1时,返回min(A[0],B[0]),如果考虑这个问题,当k==1时,会出现死循环的情况;

    如果只是单纯按照上面的解法来写代码的话,还需要考虑k/2与m和n的关系,对于这个问题,可以设定m<n,如果不是话,就交换数组A和数组B(也就是递归调用原函数,但是把实参交换即可)。这样的情况下,只要考虑m与k/2的关系即可,也就是说对于上面的三种情况,将比较A[k/2-1]和B[k/2-1]转化为比较A[min(k/2, m)-1]和B[k - min(k/2, m) -1],具体情况仍然可以根据数轴进行分析。
   
  (我自己的思路是如何将这个问题分解为不断求解两个排好序的小数组中位数的问题,然后递归使用二分搜索进行,这个思路也用到了二分搜索,也考虑到了A[m/2]和B[n/2]的关系,但是,我一直无法将问题分解为每次都是比较每个数组中间位置的大小的情况。这里主要出现的问题是,没有考虑到此处用二分搜索时,总的长度为k,即为需要搜索的第k小的数的k值)。



三.实现代码

class Solution
{
public:

    int Min(int A, int B)
    {
        if (A > B)
        {
            return B;
        }
        return A;
    }


    double findNoKMinInSortedArrays(int* A, int m, int* B, int n, int k)
    {
        // set the m to be not bigger than n.
        if (m > n)
        {
            return findNoKMinInSortedArrays(B, n, A, m, k);
        }


        //
        if (m == 0)
        {
            return B[k - 1];
        }


        //
        if (k == 1)
        {
            return Min(A[0], B[0]);
        }


        int stake = k / 2;
        int Index_A = Min(stake, m);
        int Index_B = k - Index_A;

        if (A[Index_A - 1] == B[Index_B - 1])
        {
            return A[Index_A - 1];
        }

        if (A[Index_A - 1] > B[Index_B - 1])
        {
            A = A;
            m = Index_A;
            B = B + Index_B;
            n = n - Index_B;
            k = k - Index_B;
        }
        else
        {
            A = A + Index_A;
            m = m - Index_A;
            B = B;
            n = Index_B;
            k = k - Index_A;
        }

        return findNoKMinInSortedArrays(A, m, B, n, k);

    }

    double findMedianSortedArrays(int A[], int m, int B[], int n)
    {
        int k = m + n;

        if ((k & 0x01) == 1)
        {
            return findNoKMinInSortedArrays(A, m, B, n, k / 2 + 1);
        }
        else
        {
            return (findNoKMinInSortedArrays(A, m, B, n, k / 2) + findNoKMinInSortedArrays(A, m, B, n, k / 2 + 1)) * 0.5;
        }

    }

};




四.体会

    这道题也算是二分搜索的一个变种,由于本题本质上还是选择第k小的数,因此,将搜索长度设定为k,这样,每次进行二分之后,都能减少k/2个元素,最多只要进行klogk次就可以完成搜索。这道题难的地方除了选择搜索的长度k之外,就是考虑边界条件了。这道题还是挺有技巧的,代码长度也不长,很适合面试的时候考,后面还需要多看几遍。



版权所有,欢迎转载,转载请注明出处,谢谢微笑





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值