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

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

例:


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


# 1 暴力解法:合并,排序,直接查找,时间复杂度O((m+n)log (m+n))

class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        for i in range(len(nums2)):
            nums1.append(nums2[i])
        nums1.sort()
        num = len(nums1)
        k = int(num/2)
        if (num & 1) == 0:
            return ((nums1[k]+nums1[(k-1)])/2)
        else:
            return (nums1[k])

# 2 合并两个有序数组,只用合并到中值即可。时间复杂度O((m+n))

class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        m = len(nums1)
        n = len(nums2)
        lens = m + n
        left, right = -1, -1  # 分割线左右两边的值
        aStart, bStart = 0, 0  # 两个数组的开始下标
        
        for i in range(lens//2 + 1):  # 只用遍历到中值即可
            left = right  # 右边界赋值给左边界
            if aStart < m and (bStart >= n or nums1[aStart] < nums2[bStart]):  # 1数组还有值,并且1数组当前下标对应的值小于2数组当前下标对应的值或者2数组已经遍历完毕
                right = nums1[aStart]  # 则将1数组当前下标对应的值赋给右边界
                aStart += 1  # 下标右移一位,判断下一个
            else:  # 与上个判断类似
                right = nums2[bStart]
                bStart += 1


        if (lens & 1) == 0:  # 按位与运算判断长度奇偶
            return (left+right)/2.0  # 为偶数的情况
        else:
            return right

# 二分法,同样查询一半的值即可,每个数组判断一半,将较小的一半直接过滤,因为是有序数组,直接判断中值即可,不必一一比较,时间复杂度为O(log (m+n))

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:

        def getK(k):  # k值,需要查询的第k大的值
            id1, id2 = 0, 0  # 数组1的下标,数组2的下标
            while True:
                # 特殊情况
                if id1 == m:  # 数组1全部在中值左边
                    return nums2[id2 + k - 1]  # 在数组2的当前下标下直接加上剩余需要判断的值
                if id2 == n:  # 数组2全部在中值左边
                    return nums1[id1 + k - 1]  # 在数组1的当前下标下直接加上剩余需要判断的值
                if k == 1:  # k等于1时表明已经排除了小于中值的值,直接返回当前下标中较小的一方即可
                    return min(nums1[id1], nums2[id2])

                # 正常情况
                newid1 = min(id1 + k // 2 - 1, m - 1)  # 数组1需要判断的位置下标
                newid2 = min(id2 + k // 2 - 1, n - 1)  # 数组2需要判断的位置下标
                p1, p2 = nums1[newid1], nums2[newid2]  # 判断下标对应的值
                if p1 <= p2:  # 若数组1的当前判断值较小,则说明判断下标以及之前的值全部都在中值左边,全部排除
                    k -= newid1 - id1 + 1  # 需要判断的k值减少排除的值
                    id1 = newid1 + 1  # 数组1从去除的下标后一位重新开始
                else:  # 同理
                    k -= newid2 - id2 + 1
                    id2 = newid2 + 1
        
        m,  n = len(nums1), len(nums2)  # 数组1,数组2的长度
        Length = m + n  # 总长度
        if Length % 2 == 1:  # 若总数组长度为奇数
            return getK((Length + 1) // 2)  # 直接返回中值下标对应的值
        else:  # 若为偶数
            return (getK(Length // 2) + getK(Length // 2 + 1)) / 2  # 返回中值左右两边的值相加取平均

三种方法,如果对时间复杂度没有要求的话,暴力还是最通俗易懂,暴力yyds |ू・ω・` )