zoukankan      html  css  js  c++  java
  • LeetCode 寻找两个有序数组的中位数(二分)

    给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

    请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

    你可以假设 nums1 和 nums2 不会同时为空。

    示例 1:

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

    则中位数是 2.0
    示例 2:

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

    则中位数是 (2 + 3)/2 = 2.5

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    题解: 两个有序数组,建议在O(log(m + n))复杂度下计算,因此容易想到是二分了,但是又是两个数组的中位数,不能合并后再二分,只能充分利用两数组的有序信息来二分结果.

    首先回忆一下中位数的意义,在有序数组中位置居中的那个数,目前有两个数组,我们定数组长度为len1和len2,合并后的总长度为len1+len2,其中中位数肯定存在于len1+len2的中间位置,也就是(len1+len2)/2 ,考虑到总数的奇偶关系,我们向上取整,即(len1+len2+1)/2.

    接着,我们知道中位数的位置必定在(len1+len2+1)/2,但因为这是混合数组,我们无法确定这个数是A数组还是B数组.

    但是我们知道,在这(len1+len2+1)/2个数字中,肯定存在一些A数组和B数组的值,至于是谁,我们用一下关系进行二分搜索.

    在这(len1+len2+1)/2个数字中,我们定义A数组可能出现了前i个数,而B数组可能出现了j=(len1+len2+1)/2-i个数,这个很好理解,即A数组中的前i个数与B数组中的前j个数组成了合并后数组的前半部分.

    为什么要说’前半部分’,而不说’一半’,因为有序的大小关系也是有意义的,可以知道,前半部分的最大值,一定小于或等于后半部分的最小值.

    通过这个关系,我们首先二分尝试A数组中到底是前几个数存在于混合后的前半部分.比如我们尝试了A[i]这个数,并通过之前的关系得到了B数组中可能取到的数B[j],这个关系即,A数组取前i个数的情况下B数组取前(len1+len2+1)/2-i个数.

    通过比较我们发现,当A[i] 取到的值 大于 B[j-1]个数 ,且 B[j] 取到的值 大于 A[i-1]个数时,此时前半部分的最大值不是A[i]就是B[j].

    为什么呢?因为我们其实在这个过程中,是尽量搜索前半部分的最大值,但是我们这个最大值搜索是建立在两个数组的基础上的,那么最大值可能来自A数组也可能来自B数组,于是在符合两数组前i大和前j大,且i+j=(len1+len2+1)/2这个条件的情况下,我们取到了两数组可能出现的最大值位置,以至于再大就会找到后半部分的值了.

    最后处理边界问题,这组数总数是奇数时,只需取一个值即可,那么这个值就是A[i-1]或B[j-1].取最大值返回

    而当是偶数个时,取前半部分的最大值以及后半部分的最小值加和除二即中位数,那么只需要对A[i]和B[j]取最小值,然后加上上一步中的最大值结果除2即可

    class Solution:
        def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
            l1=len(nums1)
            l2=len(nums2)
            if l1>l2:
                l1,l2,nums1,nums2=l2,l1,nums2,nums1
            
            l=0
            r=l1
            half=(l1+l2+1)//2
            while l<=r:
                mid=(l+r)//2
                half_mid=half-mid
                if mid<l1 and nums1[mid]<nums2[half_mid-1]:
                    l=mid+1
                elif mid>0 and nums1[mid-1]>nums2[half_mid]:
                    r=mid-1
                else:
                    if mid==0: ans= nums2[half_mid-1]
                    elif half_mid==0:ans= nums1[mid-1]
                    else:ans= max(nums1[mid-1],nums2[half_mid-1])
                    if (l1+l2)%2==1:
                        return ans
                    if mid==l1:res=nums2[half_mid]
                    elif half_mid==l2:res=nums1[mid]
                    else :res=min(nums2[half_mid],nums1[mid])
                    return (ans+res)/2
    
  • 相关阅读:
    js获得动态生成的标签
    自定义字段在List和ClassList等标签里的使用方法
    asp.net dropdownlist 取不到值
    MXCMS新增标签IFrame 包含标签
    JS打印
    Flash图表解决方案 Finger Chart
    推荐个免费的客户端控件
    C#利用反射获取对象属性值
    位置导航MXCMS Position标签说明
    OAuth简介
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135643.html
Copyright © 2011-2022 走看看