寻找两个正序数组的中位数

寻找两个正序数组的中位数

在这篇博客文章中,我们将探讨如何解决一个经典的算法问题:如何在给定两个正序数组的情况下,找出它们的中位数。这个问题通常用于找到一组数据的中间值,而且要求算法的时间复杂度为 O(log (m+n)),其中 m 和 n 分别是两个数组的长度。

问题描述

给定两个正序数组 nums1nums2,我们的任务是找出它们的中位数。为了更好地理解问题,让我们看看一些示例。

示例 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

解决方案

为了解决这个问题,我们可以采用分治法的思想。首先,我们需要确保两个输入数组都是正序的。接下来,我们可以将这两个数组合并成一个正序数组,然后找出中位数。

合并数组

要合并两个正序数组,我们可以使用一个新的数组来保存合并后的结果。我们需要维护两个指针,分别指向两个数组的起始位置。然后,我们依次比较两个指针指向的元素,将较小的元素放入合并后的数组中,并移动指向该元素的指针。重复这个过程,直到两个数组都被完全合并。

让我们用 Java 代码来实现这一步骤:

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m = nums1.length;
        int n = nums2.length;
        int[] merged = new int[m + n];
        
        int i = 0, j = 0, k = 0;
        while (i < m && j < n) {
            if (nums1[i] < nums2[j]) {
                merged[k] = nums1[i];
                i++;
            } else {
                merged[k] = nums2[j];
                j++;
            }
            k++;
        }
        
        // 处理剩余元素
        while (i < m) {
            merged[k] = nums1[i];
            i++;
            k++;
        }
        while (j < n) {
            merged[k] = nums2[j];
            j++;
            k++;
        }
        
        // 现在 merged 数组包含了两个数组的合并结果
        // 下一步是找出中位数
        // ...
    }
}

找出中位数

要找出合并后数组的中位数,我们需要考虑数组的长度是奇数还是偶数。如果长度是奇数,中位数就是数组中的中间元素。如果长度是偶数,中位数是中间两个元素的平均值。

让我们继续完善上面的代码来找出中位数:

// ... 上面的合并数组的代码

// 找出中位数
if ((m + n) % 2 == 1) {
    // 数组长度为奇数
    return merged[(m + n) / 2];
} else {
    // 数组长度为偶数
    int mid1 = merged[(m + n) / 2 - 1];
    int mid2 = merged[(m + n) / 2];
    return (double) (mid1 + mid2) / 2.0;
}

完整的解决方案

下面是完整的 Java 代码,包括合并数组和找出中位数的部分:

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m = nums1.length;
        int n = nums2.length;
        int[] merged = new int[m + n];
        
        int i = 0, j = 0, k = 0;
        while (i < m && j < n) {
            if (nums1[i] < nums2[j]) {
                merged[k] = nums1[i];
                i++;
            } else {
                merged[k] = nums2[j];
                j++;
            }
            k++;
        }
        
        // 处理剩余元素
        while (i < m) {
            merged[k] = nums1[i];
            i++;
            k++;
        }
        while (j < n) {
            merged[k] = nums2[j];
            j++;
            k++;
        }
        
        // 找出中位数
        if ((m + n) % 2 == 1) {
            // 数组长度为奇数
            return merged[(m + n) / 2];
        } else {
            // 数组长度为偶数
            int mid1 = merged[(m + n) / 2 - 1];
            int mid2 = merged[(m + n) / 2];
            return (double) (mid1 + mid2) / 2.0;
        }
    }
}

测试

为了验证我们的解决方案,让我们用示例测试一下:

public static void main(String[] args) {
    Solution solution = new Solution();
    
    int[] nums1 = {1, 3};
    int[] nums2 = {2};
    double result1 = solution.findMedianSortedArrays(nums1, nums2);
    System.out.println("中位数: " + result1);
    
    int[] nums3 = {1, 2};
    int[] nums4 = {3, 4};
    double result2 = solution.findMedianSortedArrays(nums3, nums4);
    System.out.println("中位数: " + result2);
}

这将输出以下结果:

中位数: 2.0
中位数: 2.5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尚可签

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值