LeetCode-4 寻找两个正序数组的中位数

题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/

题目描述

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。

 

示例 1:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2


示例 2:

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5


示例 3:

输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000


示例 4:

输入:nums1 = [], nums2 = [1]
输出:1.00000


示例 5:

输入:nums1 = [2], nums2 = []
输出:2.00000
 

提示:

nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106

解题思路

单从题干来说,这就是一道归并排序题,最初的想法是将两个vector数量求和除以二得到n,然后归并排序找出第n个数来,不出所料,时间超出限制。

困难题果然不简单,关键是“算法的时间复杂度应该为 O(log (m+n)) ”,如果使用归并排序的方法,那么时间复杂度必然是O(m+n),还是太久了。

这个时候其实理所当然应该想到二分法,不过还有另一种解法也十分的有趣。

假设两个数组分别为A,B,数组程度分别为m,n:

中位数的意义就是将一个数组平均的分成两个部分,这两个部分有相同数目的元素,对于未合并的两个数组来说也一样,假设我们将A数组在第i个地方分开,B数组在第j个地方分开,那么A[i]或者B[j]是中位数的必须满足的条件就是:

1、i + j  = m - i + n - j(m+n为偶数时)或者i + j = m - i + n - j + 1(m + n为奇数)。

2、A[i - 1] <= B[j] 并且 B[j - 1] <= A[i].

通过条件1,在确定i的情况下可以确定j的值,那么我们需要使用二分法找到一个i满足条件2便可以找到中位数。

在确定i之后,比较A中第i个数和B中第j个数,如果m+n是奇数,那么A中第i个数和B中第j个数中最大的那个就是中位数,如果m+n是偶数,那么还需要找到划分出来的后数组中最小值,即A中第i+1个数和B中第j+1个数中最大的那个,将前数组的最大值与后数组的最小值求均值,就是中位数了。

 

源码展示

复制代码
class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        m=min(len(nums1),len(nums2))
        n=max(len(nums1),len(nums2))
        A=nums1 if len(nums1)<len(nums2) else nums2
        B=nums2 if len(nums2)>len(nums1) else nums1
        imin=0
        imax=m

        while imin<=imax:
            i=int((imin+imax)/2)
            j=int((m+n+1)/2-i)
            if  i<imax and B[j-1]>A[i]:
                imin=i+1
            elif  i>imin and A[i-1]>B[j]:
                imax=i-1
            else:
                leftx=0
                if i==0 : leftx=B[j-1]
                elif j==0 : leftx=A[i-1]
                else:
                    leftx=max(A[i-1],B[j-1])
                if (m+n)%2==1: return  leftx
                rightx=0
                if i==m :rightx=B[j]
                elif j==n :rightx=A[i]
                else:
                    rightx=min(A[i],B[j])
                return (leftx+rightx)/2.0
复制代码

 

运行结果

 

posted @   过客匆匆,沉沉浮浮  阅读(45)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示