返回
中位数,寻找两个正序数组的中位数,实战与讲解
前端
2023-09-28 04:41:49
破解 LeetCode 第 4 题:寻找两个正序数组的中位数
前言
对于踏上 LeetCode 征程的众多程序员而言,第 4 题「寻找两个正序数组的中位数」可谓是一道经典难题。它考验着你的算法思维和编程能力,要求你在 O(m + n) 的时间复杂度内(其中 m 和 n 分别是两个数组的长度),找出两个有序数组的中位数。
解题思路
理解中位数的概念
中位数是指按顺序排列的一组数据中位于中间位置的数字。而本题中,中位数指的是合并两个数组后的中位数。
巧用数组有序特性
由于两个数组都是有序排列的,因此我们可以利用这个特性来优化我们的解题思路。我们将两个数组视为一个整体,然后从头到尾遍历这两个数组,每次比较两个数组当前位置的元素,选择较小的元素作为中位数。如果遍历到两个数组的末尾,则中位数就是两个数组中最后一个元素的平均值。
具体步骤
- 初始化两个指针,分别指向两个数组的第一个元素。
- 比较两个指针指向的元素,选择较小的元素作为中位数。
- 将较小的元素移出数组,并将对应的指针后移一位。
- 重复步骤 2 和步骤 3,直到两个指针都指向数组的末尾。
- 如果两个指针都指向数组的末尾,则中位数就是两个数组中最后一个元素的平均值。
代码实现
def find_median_sorted_arrays(nums1, nums2):
"""
寻找两个正序数组的中位数
:param nums1: 第一个数组
:param nums2: 第二个数组
:return: 中位数
"""
# 初始化两个指针
p1 = 0
p2 = 0
# 两个数组的长度
m = len(nums1)
n = len(nums2)
# 合并后的数组的长度
l = m + n
# 如果合并后的数组的长度是奇数,则中位数是中间的元素
if l % 2 == 1:
mid = l // 2 + 1
# 如果合并后的数组的长度是偶数,则中位数是中间两个元素的平均值
else:
mid = l // 2
# 初始化中位数
median = 0
# 遍历两个数组
while p1 < m and p2 < n:
# 比较两个指针指向的元素
if nums1[p1] < nums2[p2]:
# 选择较小的元素作为中位数
median = nums1[p1]
# 将较小的元素移出数组
p1 += 1
else:
# 选择较小的元素作为中位数
median = nums2[p2]
# 将较小的元素移出数组
p2 += 1
# 如果已经找到了中位数,则返回中位数
if mid == 1:
return median
# 递减中位数的位置
mid -= 1
# 如果第一个数组还有元素,则将剩余元素添加到合并后的数组中
while p1 < m:
median = nums1[p1]
p1 += 1
mid -= 1
if mid == 1:
return median
# 如果第二个数组还有元素,则将剩余元素添加到合并后的数组中
while p2 < n:
median = nums2[p2]
p2 += 1
mid -= 1
if mid == 1:
return median
# 返回中位数
return median
# 测试代码
nums1 = [1, 3, 5]
nums2 = [2, 4, 6]
print(find_median_sorted_arrays(nums1, nums2)) # 3.5
nums1 = [1, 2]
nums2 = [3, 4]
print(find_median_sorted_arrays(nums1, nums2)) # 2.5
复杂度分析
- 时间复杂度:O(m + n),其中 m 和 n 分别是两个数组的长度。
- 空间复杂度:O(1),因为不需要额外的空间来存储中间结果。
常见问题解答
-
为什么时间复杂度是 O(m + n)?
因为我们遍历了两个数组中的元素,并且在最坏的情况下,我们需要遍历所有元素才能找到中位数。因此,时间复杂度与两个数组的长度之和成正比。 -
为什么空间复杂度是 O(1)?
因为我们不需要额外的空间来存储中间结果。我们只使用两个指针来跟踪两个数组中当前位置的元素。 -
如何处理两个数组长度相等的情况?
如果两个数组长度相等,则中位数就是两个数组中最后一个元素的平均值。 -
如果两个数组中包含重复元素,该怎么办?
重复元素不会影响中位数的计算。我们可以像往常一样比较元素,选择较小的元素。 -
除了使用两个指针,还有其他方法可以找到中位数吗?
是的,还有一些其他方法可以找到中位数,例如使用二分查找或合并两个数组。