Python实现两个有序数组中位数的二分查找算法详解
本文详解如何在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寻找两个有序数组中位数的完整过程,希望能为读者提供帮助。如有任何疑问,欢迎留言,小编会及时回复。感谢大家对本站的支持!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









