在这篇博客文章中,我们将探讨如何解决一个经典的算法问题:如何在给定两个正序数组的情况下,找出它们的中位数。这个问题通常用于找到一组数据的中间值,而且要求算法的时间复杂度为 O(log (m+n)),其中 m 和 n 分别是两个数组的长度。
给定两个正序数组 nums1
和 nums2
,我们的任务是找出它们的中位数。为了更好地理解问题,让我们看看一些示例。
输入:
nums1 = [1, 3]
nums2 = [2]
输出:
2.00000
解释:
合并数组 = [1, 2, 3]
,中位数为 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