题目没有时间复杂度的严格要求(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))),是处理“两个有序数组中位数”问题的经典方案。



京公网安备 11010502036488号