4. 寻找两个正序数组的中位数(一)

1,205 阅读2分钟

题目描述

给定两个大小分别为 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

解题思路1: 2个数组同时遍历法

  1. 假设2个数组元素个数总数为 2n, 那么中位数的idx=n, 我们给2个数组分别一个idx进行遍历, 哪个数组的当前元素小, 我们就让idx后移, 直到2个idx的和为n. 这样就找到了中位数
  2. 因为中位数分奇偶的情况, 所以我们还需要做特殊的处理:
    1. 如果是奇数的情况, 我们遍历的次数为: n+1 次, 取最后一次结果返回
    2. 如果是偶数情况, 我们最终也是需要遍历 n+1 次, 取最后2次结果的和/2返回
    3. 根据这样的现象, 我们可以将奇数/偶数的遍历统一处理. 用一个值保存当前遍历的结果, 一个值保存上一次遍历的结果, 这样在偶数的情况我们就能拿到2个结果去处理

示例代码

def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
    count = (len(nums1) + len(nums2))
    h1 = h2 = id1 = id2 = 0

    while (id1 + id2) <= count // 2:
        h1 = h2

        if id1 < len(nums1) and (id2 >= len(nums2) or nums1[id1] < nums2[id2]):
            h2 = nums1[id1]
            id1 += 1
        else:
            h2 = nums2[id2]
            id2 += 1

    if count & 1 == 0:
        return (h1 + h2) / 2
    else: 
        return h2

注意

  1. 这个题解能 Accepted, 但是不满足题意时间复杂度应该为 O(log (m+n))的要求. 所以下一篇会介绍满足要求的题解
  2. 这个题目其实是2个有序数组排序后第K个元素题解的特殊情况, K = (l1 + l2)/2