返回

中位数,寻找两个正序数组的中位数,实战与讲解

前端

破解 LeetCode 第 4 题:寻找两个正序数组的中位数

前言

对于踏上 LeetCode 征程的众多程序员而言,第 4 题「寻找两个正序数组的中位数」可谓是一道经典难题。它考验着你的算法思维和编程能力,要求你在 O(m + n) 的时间复杂度内(其中 m 和 n 分别是两个数组的长度),找出两个有序数组的中位数。

解题思路

理解中位数的概念

中位数是指按顺序排列的一组数据中位于中间位置的数字。而本题中,中位数指的是合并两个数组后的中位数。

巧用数组有序特性

由于两个数组都是有序排列的,因此我们可以利用这个特性来优化我们的解题思路。我们将两个数组视为一个整体,然后从头到尾遍历这两个数组,每次比较两个数组当前位置的元素,选择较小的元素作为中位数。如果遍历到两个数组的末尾,则中位数就是两个数组中最后一个元素的平均值。

具体步骤

  1. 初始化两个指针,分别指向两个数组的第一个元素。
  2. 比较两个指针指向的元素,选择较小的元素作为中位数。
  3. 将较小的元素移出数组,并将对应的指针后移一位。
  4. 重复步骤 2 和步骤 3,直到两个指针都指向数组的末尾。
  5. 如果两个指针都指向数组的末尾,则中位数就是两个数组中最后一个元素的平均值。

代码实现

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),因为不需要额外的空间来存储中间结果。

常见问题解答

  1. 为什么时间复杂度是 O(m + n)?
    因为我们遍历了两个数组中的元素,并且在最坏的情况下,我们需要遍历所有元素才能找到中位数。因此,时间复杂度与两个数组的长度之和成正比。

  2. 为什么空间复杂度是 O(1)?
    因为我们不需要额外的空间来存储中间结果。我们只使用两个指针来跟踪两个数组中当前位置的元素。

  3. 如何处理两个数组长度相等的情况?
    如果两个数组长度相等,则中位数就是两个数组中最后一个元素的平均值。

  4. 如果两个数组中包含重复元素,该怎么办?
    重复元素不会影响中位数的计算。我们可以像往常一样比较元素,选择较小的元素。

  5. 除了使用两个指针,还有其他方法可以找到中位数吗?
    是的,还有一些其他方法可以找到中位数,例如使用二分查找或合并两个数组。