LeetCode 4. 寻找两个正序数组的中位数
给定两个大小分别为 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
代码1:
# python
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
# 将两个列表合并成一个
num = nums1 + nums2
# 对合并后的列表进行排序
num.sort()
# 找到合并后列表的长度
n = len(num)
# 检查元素的个数是否为偶数
if n % 2 == 0:
# 如果是偶数,返回中间两个元素的平均值
return (num[n // 2] + num[n // 2 - 1]) / 2
else:
# 如果是奇数,返回中间的那个元素
return num[n // 2]
上面的代码时间复杂度为O(m+n)log(m+n)
,不符合题意要求。
代码2:
# python
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
# 保证 nums1 是较短的那个数组,如果 nums1 长度大于 nums2,交换它们
if len(nums1) > len(nums2):
nums1, nums2 = nums2, nums1
# 获取两个数组的长度
m, n = len(nums1), len(nums2)
# 对 nums1 进行二分查找
left, right = 0, m
half_len = (m + n + 1) // 2 # 整个合并后的数组的一半长度
while left <= right:
# 在 nums1 中找到合适的分割点
i = (left + right) // 2
# 在 nums2 中找到对应的分割点
j = half_len - i
# 检查分割是否合适
if i < m and nums2[j - 1] > nums1[i]:
# i 太小,调整 left
left = i + 1
elif i > 0 and nums1[i - 1] > nums2[j]:
# i 太大,调整 right
right = 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
这个代码时间复杂度为Olog(m+n)
,符合题意。