• [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 将有可能为负数。因此在程序的开始进行检查。
    • 边界条件的讨论。当 i0, j0, im, jn 时,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;
    }
    
    
  • 相关阅读:
    hdu1003 Max Sum【最大连续子序列之和】
    HDU 2639 骨头收集者 II【01背包 】+【第K优决策】
    poj2184 Cow Exhibition【01背包】+【负数处理】+(求两个变量的和最大)
    HDU 2955_Robberies 小偷抢银行【01背包】
    UVa 562
    HDU 1159 Common Subsequence 【最长公共子序列】模板题
    hdu 5748 Bellovin【最长上升子序列】
    POJ 3903 Stock Exchange 【最长上升子序列】模板题
    UVA 624 CD[【01背包】(输出路径)
    hdu 2546 饭卡【01背包】
  • 原文地址:https://www.cnblogs.com/fanling999/p/7817283.html
Copyright © 2020-2023  润新知