题目没有时间复杂度的严格要求(O(log(m+n))),直接合并两个数组(时间复杂度 O(m+n))解决问题。

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param nums1 int整型一维数组 
# @param nums2 int整型一维数组 
# @return double浮点型
#
class Solution:
    def Median(self , nums1: List[int], nums2: List[int]) -> float:
        # write code her
        nums = sorted(nums1+nums2)
        n = len(nums)
        if n%2:
            return nums[n//2]
        else:
            return (nums[n//2-1]+nums[n//2])/2

题目原意应该是:

核心思路:二分法定位分割点

中位数的本质是将合并后的数组划分为左右两部分,使得:

  • 左边所有元素 ≤ 右边所有元素;
  • 左边元素个数 ≥ 右边(奇数长度时左边多一个)。

对于两个有序数组,我们可以通过二分查找分割点,将 nums1 和 nums2 分别划分为左右两部分,使得:

  • nums1 的左半部分 + nums2 的左半部分 nums1 的右半部分 + nums2 的右半部分;
  • 左半部分总元素数为 (m+n+1)//2(向上取整,保证奇数长度时左边多一个)。

算法步骤详解

步骤 1:统一数组长度(优化二分范围)

为了减少二分查找的范围,确保 nums1 是较短的数组(若 nums1 更长,则交换 nums1 和 nums2)。这样,二分查找仅需在较短数组上进行,降低时间复杂度。

步骤 2:二分查找分割点

在 nums1 中二分查找分割点 i,并计算 nums2 的对应分割点 j

  • i 表示 nums1 左半部分的元素个数(范围:0 ≤ i ≤ m);
  • j = (m + n + 1) // 2 - i,保证左半部分总元素数为 (m+n+1)//2(向上取整)。
步骤 3:处理边界值(分割点越界)

分割点 i 或 j 可能为 0(左半部分为空)或等于数组长度(右半部分为空),需用极值(-∞ 或 +∞)处理:

步骤 4:计算中位数

根据合并后数组的长度(m+n)的奇偶性,计算中位数:

  • 奇数:左半部分最大值(max(nums1_left, nums2_left));
  • 偶数:左半部分最大值与右半部分最小值的平均值((max(...) + min(...)) / 2)。

关键逻辑解析

1. 数组交换的意义

将较长数组与较短数组交换,确保二分查找在较短数组上进行,减少二分次数(如 m=3, n=5 时,二分范围是 0~3 而非 0~5)。

2. 分割点的数学意义

j = (m + n + 1) // 2 - i 保证 左半部分总元素数为 (m+n+1)//2

  • 若 m+n 为奇数,左半部分比右半部分多 1 个元素,中位数是左半部分的最大值;
  • 若 m+n 为偶数,左半部分与右半部分元素数相等,中位数是两部分的中间值平均。
3. 边界值处理

通过 Integer.MIN_VALUE 和 Integer.MAX_VALUE 处理“左半部分为空”或“右半部分为空”的情况,确保比较逻辑的一致性。

4. 二分循环的细节

使用 (left + right + 1) / 2 向上取整,避免 left 和 right 相邻时的死循环(如 left=1, right=2 时,mid=2 而非 1,确保范围缩小)。

该方法通过 二分查找分割点 避免了数组的完全合并,将时间复杂度优化到 O(log(min(m,n)))(等价于 O(log(m+n))),是处理“两个有序数组中位数”问题的经典方案。