[array] leetCode-4-Median of Two Sorted Arrays-Hard

leetCode-4-Median of Two Sorted Arrays-Hard

descrition

There are two sorted arrays nums1 and nums2 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)).

example 1

nums1 = [1, 3]
nums2 = [2]

The median is 2.0

example 2

nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

解析

注意题目对时间复杂度的要求:O(log (m+n)),在加上数组有序的条件,此处应该联想到二分搜索的优化。那要如何用呢?看下面分析。(也可以参考 leetcode 中的 solution,解释得也很好)

定义函数接口:

double findMedianSortedArrays(vector<int>& A, vector<int>& B)

即两个数组 A, B,假设大小分别为 m 和 n

将数组 A 根据任意位置 i 分成左右两部分,同理 B 根据任意位置 j 也分成左右两部分,如下:

left_part                | right_part
A[0], A[1], ..., A[i-1]  | A[i], A[i+1], ... , A[m]  
B[0], B[1], ..., B[j-1]  | B[j], B[j+1], ... , B[n]

由中位数的定义以及数组有序的条件,我们希望以上划分满足:

len(left_part) = len(right_part) 
    ==> i+j = m-i + n-j (or: i+j = m-i + n-j + 1 (奇数的情况,将多的一个放到左边))
    ==> j = (m+n+1)/2 - i, i=[0,m]
max(left_part) <= min(right_part) ==> A[i-1] <= B[j] && B[j-1] <= A[i]

由此我们只需要在有序数组 A 上进行二分查找,确定 i 的位置,使得以上条件满足即可找到合适的划分。在此基础上我们可以根据划分边界求得 median。

初始条件:imin = 0, imax = m;
当 imin <= imax 时候的一次迭代: 
    i = (imin + imax) / 2
    j = (m+n+1)/2 - i
    // 此处讨论暂时不考虑边界情况,即假设 i 和 j 都合法
    // 只可能出现以下几种情况:
    (1) A[i-1] <= B[j] && B[j-1] <= A[i]
        // 划分满足要求,可以停止循环
    (2) A[i-1] > B[j] 
        // A[i-1] 太大,也就是我们要想办法调整 i 的值使得  A[i-1] <= B[j] 成立
        // 这个时候如果我们增大 i,只会使得 A[i-1] 更大 (因为数组是非递减有序的)
        // 因此我们只能通过减小 i,尝试找到更小的 A[i-1],因此作出如下调整
        imax = i-1
    (3) B[j-1] > A[i]
        // B[j-1] 太大,同理我们应该减小 j
        // 从另一个角度,减小 j 就相当于增大 i,因此我们作出以下调整
        imin = i+1

几个细节:

  • m <= n 必须成立。因为 j = (m+n+1)/2 – i,如果 m>n,那么 j 将有可能为负数。因此在程序的开始进行检查。
  • 边界条件的讨论。当 i==0, j==0, i==m, j==n 时,A[i-1], B[j-1], A[i], B[j] 都是不成立的。如果 i 和 j 都满足要求时,我们需要检查 A[i-1] <= B[j] && B[j-1] <= A[i] 是否成立,那么当 i 和 j 到达边界条件时,我们也就不需要检查其中的某一个条件,比如当 i == 0 时, A 数组的左边为空,我们就不需要检查 A[i-1] <= B[j] 这个条件。(参看代码)

code


#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Solution{
public:
    double findMedianSortedArrays(vector<int>& A, vector<int>& B){
        // insure the size of A is less than and equal to the size of B
        if(A.size() > B.size())
            swap(A, B);
        int m = A.size();
        int n = B.size();
        // m <= n

        // when m+n is odd, the follow equation will insure the median 
        // will be assined into left part. 
        int lenLeft = (m+n+1) / 2; 

        // binary search 
        int imin = 0, imax = m;
        while(imin <= imax){
            int i = (imin + imax) / 2;
            int j = lenLeft - i;
            if( i>0 && A[i-1] > B[j]){
                // A[i-1] too large, decreasing i
                // i > 0 ==> j<n, because j = (m+n+1) / 2 - i < (m+n+1) / 2 < 2n+1/2 < n
                imax = i-1;
            }else if ( i<m && B[j-1] > A[i]){
                // A[i] too small, increasing i
                // i < m ==> j>0, because j = (m+n+1) / 2 - i > (m+n+1) / 2 - m > (2m+1)/2 - m > 0
                imin = i+1;
            }else{
                // perfit
                int maxLeft = 0;
                if(i == 0){
                    maxLeft = B[j-1];
                }else if (j == 0){
                    maxLeft = A[i-1];
                }else{
                    maxLeft = max(B[j-1], A[i-1]);
                }

                if( ((n+m)&1) == 1) // odd
                    return maxLeft;

                int minRight = 0;
                if(i == m){
                    minRight = B[j];
                }else if (j == n){
                    minRight = A[i];
                }else{
                    minRight = min(B[j], A[i]);
                }

                return (maxLeft + minRight)*1.0 / 2.0;
            }
        }

        return 0.0;
    }
};

int main()
{
    return 0;
}

作者:fanling999 链接:https://www.cnblogs.com/fanling999/

    原文作者:fanling999
    原文地址: https://www.cnblogs.com/fanling999/p/7817283.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞