Python实现两个有序数组中位数的二分查找算法详解

阿橙
阿橙
发布时间:2026-10-13 | 2人浏览过
原创

本文详解如何在Python中高效求解两个有序数组的中位数。通过二分查找法,利用递归思想与对称性定理,将时间复杂度优化至log级别。文章深入分析了数组长度差异时的元素剔除策略,并提供了完整的LeetCode标准解法代码,帮助开发者掌握核心算法逻辑。

Python寻找两个有序数组的中位数

审题分析:

首先,题目要求“找出”特定值,这明确指向一道查找算法类的题目。

其次,题目对算法复杂度有log级别的要求,这强烈暗示我们需要使用二分查找(Binary Search)策略。

在实现二分查找时,通常采用递归方式进行处理。

递归实现主要包含两个部分: (1)递归体:定义当前步骤的操作逻辑。 (2)终止条件:确定递归结束的标准。

解题思路推导:

核心定理:

1. 在有序数组中,有一半的元素小于或等于该数组的中位数,另一半元素大于或等于中位数(注:若数组元素个数为奇数,此处“一半”并非严格的1/2概念)。

2. 若我们从其中一个数组中移除比中位数小的k个元素,同时从另一个数组中移除比中位数大的k个元素,则合并后的子数组的中位数与原数组合并后的中位数保持一致。

eg:[1,2,3],[1,2,3] => [1,1,2,2,3,3]

例如,对于数组[2,3]和[1,2],合并后为[1,2,2,3],中位数未变。这是一个特例,读者可自行验证其他情况。需要注意的是,当两个数组长度不一致时,不能简单地各自去掉一半元素,而必须去掉相同数量的元素,具体原因将在下文详细阐述。

具体解题步骤:

假设两个有序数组的中位数分别为a[m1]和b[m2]。

1. 如果a[m1] == b[m2],说明此时刚好有一半的元素小于a[m1],因此a[m1]即为所求的中位数。可参考上述示例理解。

2. 如果a[m1] < b[m2],根据定理1可知,最终的中位数只可能出现在a[n1/2 ~ n1-1]区间或者b[0 ~ n2/2]区间内。也就是说,合并这两个子数组得到的中位数与原数组合并后的中位数相同。根据定理2,我们可以进行如下操作:

1. 当两个数组长度相同时,直接去除一半元素是合理的。

2. 当数组长度不同时,若直接去除一半,中位数可能会发生偏移。解决方案是:每次去除相同数量的元素。为什么?假设n1 < n2,我们两个数组都只去掉n1/2个元素。此时搜索范围不再是简单的a[n1/2 ~ n1-1]或b[0 ~ n2/2],而是调整为a[n1/2 ~ n1-1]或者b[0 ~ (-n1/2+n2-1)]。

结论:在长度不一致的情况下,我们只能删除较短数组a的前n1/2个元素(向下取整)。

3. 如果a[m1] > b[m2],分析逻辑与上述类似,中位数只能出现在a的前半段或者b的后半段。即中位数位于a[0 ~ n1/2]和b[n1/2 ~ n2-1]之间,且这两部分合并后的中位数与原中位数相同。

参考代码:LeetCode标准参考答案

class Solution:
  def findMedianSortedArrays(self, nums1, nums2):
    """
    :type nums1: List[int]
    :type nums2: List[int]
    :rtype: float
    """
    m, n = len(nums1), len(nums2)
    if m > n:
      nums1, nums2, m, n = nums2, nums1, n, m
    if n == 0:
      raise ValueError
    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]:
        # i is too small, must increase it
        imin = i + 1
      elif i > 0 and nums1[i-1] > nums2[j]:
        # i is too big, must decrease it
        imax = i - 1
      else:
        # i is perfect
        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

总结

以上介绍了使用Python寻找两个有序数组中位数的完整过程,希望能为读者提供帮助。如有任何疑问,欢迎留言,小编会及时回复。感谢大家对本站的支持!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表