4. 寻找两个排序数组的中位数

81 阅读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

解题思路

为了找到两个有序数组的中位数,我们可以合并两个数组后找出中位数。但合并数组的时间复杂度为 O(m+n),不符合题目要求的 O(log (m+n))。因此,我们采用二分搜索算法,寻找一个合适的分割线,将两个数组分别分割为左右两部分,左边所有元素都小于右边,且左边元素的个数等于右边或多一个,这样中位数可以轻易地从分割线附近的元素中计算得出。

代码

class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        # 确保 nums1 是较短的数组
        if len(nums1) > len(nums2):
            nums1, nums2 = nums2, nums1

        m, n = len(nums1), len(nums2)
        imin, imax, half_len = 0, m, (m + n + 1) // 2

        while imin <= imax:
            i = (imin + imax) // 2
            j = half_len - i
            if i < m and nums2[j-1] > nums1[i]:
                imin = i + 1
            elif i > 0 and nums1[i-1] > nums2[j]:
                imax = i - 1
            else:
                if i == 0: max_of_left = nums2[j-1]
                elif j == 0: max_of_left = nums1[i-1]
                else: max_of_left = max(nums1[i-1], nums2[j-1])

                if (m + n) % 2 == 1:
                    return max_of_left

                if i == m: min_of_right = nums2[j]
                elif j == n: min_of_right = nums1[i]
                else: min_of_right = min(nums1[i], nums2[j])

                return (max_of_left + min_of_right) / 2.0

运行

使用上述代码,我们可以获得以下测试用例的结果:

sol = Solution()
print(sol.findMedianSortedArrays([1, 3], [2]))  # 输出应为 2
print(sol.findMedianSortedArrays([1, 2], [3, 4]))  # 输出应为 2.5

总结

在解决此问题时,我们通过二分搜索算法优化了查找中位数的过程,避免了合并数组带来的额外时间复杂度。最终,我们实现了一个高效的算法,满足了题目对时间复杂度的要求,即  O(log (m+n))。这一方法不仅适用于本题,还能够为处理其他复杂排序问题提供一种有效的算法思路。

题目链接

leetcode.cn/problems/me…