ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

4. Median of Two Sorted Arrays

2020-11-29 14:59:56  阅读:231  来源: 互联网

标签:Arrays dfrac Median len int part 数组 Sorted left


文章目录

1题目理解

输入:2个已经排序号的int数组nums1,nums2
输出:这两个数组合并后的中位数
要求:m是nums1的长度,n是nums2的长度。时间复杂度应该是O(log(m+n))。
例子:
nums1 = [1, 3]
nums2 = [2]

The median is 2.0

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

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

2 二分查找解题

这道题目如果不要求时间复杂度的话,很简单。把两个数组合并。如果长度为奇数,找到中间位置的下标返回该元素。如果长度是偶数,则找到中间两个元素,求平均值返回。要符合时间复杂度要求就要用二分。以下内容来源于力扣,只看解法四。
这种解法在一刷的时候没看明白,现在二刷更清楚了。知道怎么从题目描述,到最终的条件。知道为什么这样做是对的。

2.1中位数的定义

中位数将一个数组分成两部分,左边元素个数等于右边元素个数,并且左边元素的值都小于右边元素的值。

2.2 数组切分

在数组中,我们在任意位置i,将数组切分为2部分。
在这里插入图片描述

由于数组A中有m个元素,所以数组A有m+1种切分方法。
i ∈ [ 0 , m ] i\in[0,m] i∈[0,m],那么
l e n ( l e f t A ) = i , l e n ( r i g h t A ) = m − i len(left_A)=i,len(right_A)=m-i len(leftA​)=i,len(rightA​)=m−i

采用同样的方式,在位置j,将数组B切分为两部分。

j ∈ [ 0 , n ] j\in[0,n] j∈[0,n],那么
l e n ( l e f t B ) = j , l e n ( r i g h t B ) = n − j len(left_B)=j,len(right_B)=n-j len(leftB​)=j,len(rightB​)=n−j

将left_A和left_B一起合并形成left_part,将right_A和right_B一起合并形成right_part。
在这里插入图片描述

当A和B的长度是偶数的时候,如果len(left_part)=len(right_part),并且max(left_part)<=min(right_part),
那么 中 位 数 = m a x ( l e f t _ p a r t ) + m i n ( r i g h t _ p a r t ) 2 中位数=\dfrac{max(left\_part)+min(right\_part)}{2} 中位数=2max(left_part)+min(right_part)​

当A和B的长度是奇数的时候,如果len(left_part)=len(right_part)+1,并且max(left_part)<=min(right_part),那么
中 位 数 = m a x ( l e f t _ p a r t ) 中位数=max(left\_part) 中位数=max(left_part)

2.3分析条件

对于奇偶情况不同,长度条件不一样,我们可以做合并。要想得到中位数需要符合上面两个条件。这两个条件可以这样理解。

1 i+j=m-i+n-j (m+n为偶数)或者 i+j=m-i+n-j+1(m+n为奇数)。等号左侧是前一部分元素个数,等号右侧是后一部分元素个数。将i,j都转到等号左边,做变换,得到 i + j = m + n + 1 2 i+j=\dfrac{m+n+1}{2} i+j=2m+n+1​。
具体过程是,m+n为偶数,对于i+j=m-i+n-j ,得到2*(i+j)=m+n,进一步 i + j = m + n 2 i+j=\dfrac{m+n}{2} i+j=2m+n​,因为m+n为偶数,其实 m + n 2 = m + n + 1 2 \dfrac{m+n}{2}=\dfrac{m+n+1}{2} 2m+n​=2m+n+1​。因为这里取的是整除,所以+1不会影响结果。例如 4 2 = 2 {\dfrac{4}{2}=2} 24​=2,4+1=5, 5 2 = 2 {\dfrac{5}{2}=2} 25​=2。所以此时, i + j = m + n + 1 2 i+j=\dfrac{m+n+1}{2} i+j=2m+n+1​

m+n为奇数, i+j=m-i+n-j+1,得到2*(i+j)=m+n+1,进一步得到 i + j = m + n + 1 2 i+j=\dfrac{m+n+1}{2} i+j=2m+n+1​。
所以条件1就是 i + j = m + n + 1 2 i+j=\dfrac{m+n+1}{2} i+j=2m+n+1​

2 0 < = i < = m 0<=i<=m 0<=i<=m, 0 < = j < = n 0<=j<=n 0<=j<=n。如果我们规定m<=n,那么对于任意的 i ∈ [ 0 , m ] i \in[0,m] i∈[0,m],都有 j = m + n + 1 2 − i ∈ [ 0 , n ] j=\dfrac{m+n+1}{2}-i \in[0,n] j=2m+n+1​−i∈[0,n]。这是因为不能让j是负数。可以举一个反例。例如m=10,n=4,当i=9的时候,j=7-9就是负数了。

3 max(left_part)<=min(right_part),的等价条件是A[i-1]<=B[j]并且B[j-1]<=A[i]。我们可以对该条件做进一步分析。
首先因为数组切分可能切在数组开始,也可能切在数组末尾。也就是说i=0,也有i=m,j=0,j=n的情况。这个时候我们假设A[-1]=B[-1]= − ∞ -\infty −∞,A[m+1]=B[n+1]= ∞ \infty ∞。这样可以保证结果值不受影响。如果i=0,那么 l e f t A = − ∞ left_A={-\infty} leftA​=−∞,最大值肯定来源于 l e f t B left_B leftB​。所以结果不影响。其他同理。

接着,我们需要证明A[i-1]<=B[j]并且B[j-1]<=A[i] 等价于,找到最大的i使得A[i-1]<=B[j], j = m + n + 1 2 − i j=\dfrac{m+n+1}{2}-i j=2m+n+1​−i。
这是因为当i从0到m主键增加,j会从n到0逐渐减小,A[i-1]递增,B[j]逐渐递减。总会找到一个最大的i,使得A[i-1]<=B[j]。
如果i是最大的,那说明i+1不满足,说明A[i]>B[j-1],也就是说B[j-1]<A[i]。和原来的条件要求是一样的。

因此,我们可以在[0,m]上找到最大的i,使得A[i-1]<=B[j],那么i,j就是切分点。前一部分元素的最大值,以及后一部分的最小值,才可能是数组的中位数。

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m = nums1.length;
        int n = nums2.length;
        if(m>n){
            return findMedianSortedArrays(nums2,nums1);
        }
        int l = 0, r =m;
        int median1=0,median2=0;
        while(l<=r){
            int i = (l+r)>>1;
            int j = (m+n+1)/2-i;
            int leftA = (i>0?nums1[i-1]:Integer.MIN_VALUE);
            int rightA = (i<m?nums1[i]:Integer.MAX_VALUE);
            int leftB = (j>0?nums2[j-1]:Integer.MIN_VALUE);
            int rightB = (j<n?nums2[j]:Integer.MAX_VALUE);
            if(leftA<=rightB){
                median1 = Math.max(leftA,leftB);
                median2 = Math.min(rightA,rightB);
                
                l = i+1;
            }else{
                r = i-1;
            }
        }
        return (m+n)%2==0?(median1+median2)/2.0:median1;
    }
}

标签:Arrays,dfrac,Median,len,int,part,数组,Sorted,left
来源: https://blog.csdn.net/flying_all/article/details/110246483

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有