题目
给定两个大小分别为 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))。这一方法不仅适用于本题,还能够为处理其他复杂排序问题提供一种有效的算法思路。