Java 中取两个有序数组的中位数
在编程与数据分析中,中位数是一个重要的统计量,其定义为在一个有序数据集中排列中间位置的数字。如果数据集的元素个数为奇数,中位数即为中间元素;若为偶数,则为中间两个元素的平均值。在这个文章中,我们将讨论如何在 Java 中计算两个有序数组的中位数,并提供代码示例。
问题描述
假设我们有两个有序数组 nums1 和 nums2,我们需要找出它们的中位数。需要注意的是,这两个数组的总长度可能是奇数或偶数。此问题的挑战在于我们希望在 O(log(min(n, m))) 的时间复杂度内解决问题,其中 n 和 m 是两个数组的长度。
示例
例如,我们有以下两个数组:
nums1 = [1, 3]
nums2 = [2]
输出的中位数应为 2.0。
另一个例子:
nums1 = [1, 2]
nums2 = [3, 4]
输出的中位数应为 (2 + 3) / 2 = 2.5。
解决方案
我们可以通过二分查找来高效地找到两个数组的中位数。以下是实现这一算法的 Java 代码示例:
public class MedianOfSortedArrays {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
if (nums1.length > nums2.length) {
int[] temp = nums1;
nums1 = nums2;
nums2 = temp;
}
int x = nums1.length;
int y = nums2.length;
int low = 0, high = x;
while (low <= high) {
int partitionX = (low + high) / 2;
int partitionY = (x + y + 1) / 2 - partitionX;
int maxX = (partitionX == 0) ? Integer.MIN_VALUE : nums1[partitionX - 1];
int minX = (partitionX == x) ? Integer.MAX_VALUE : nums1[partitionX];
int maxY = (partitionY == 0) ? Integer.MIN_VALUE : nums2[partitionY - 1];
int minY = (partitionY == y) ? Integer.MAX_VALUE : nums2[partitionY];
if (maxX <= minY && maxY <= minX) {
if ((x + y) % 2 == 0) {
return (Math.max(maxX, maxY) + Math.min(minX, minY)) / 2.0;
} else {
return Math.max(maxX, maxY);
}
} else if (maxX > minY) {
high = partitionX - 1;
} else {
low = partitionX + 1;
}
}
throw new IllegalArgumentException("Input arrays are not sorted.");
}
}
代码解析
- 数组大小比较:首先,我们确保
nums1是更小的数组。这样可以减少二分查找的复杂度。 - 二分查找:我们在较小的数组上执行二分查找,计算分割点。
- 分割点计算:根据当前的分割点,我们可以计算两边的临界值
maxX,minX,maxY,minY。 - 条件判断:
- 如果
maxX <= minY并且maxY <= minX,则找到了合适的分割位置。 - 根据总长度是奇数还是偶数来决定返回的中位数。
- 如果
- 调整分割位置:如果条件不满足,则调整分割点继续查找。
ER图表示
为了更好地理解我们的问题,我们可以用 ER 图表示数组之间的关系。以下是用 Mermaid 语法表示的 ER 图:
erDiagram
NUMS1 {
integer id
integer value
}
NUMS2 {
integer id
integer value
}
NUMS1 ||--o{ NUMS2 : combines
表格表示
在考虑的所有示例中,我们可以用以下表格来展示所有可能的中位数:
| 示例 | nums1 | nums2 | 中位数 |
|---|---|---|---|
| 示例 1 | [1, 3] |
[2] |
2.0 |
| 示例 2 | [1, 2] |
[3, 4] |
2.5 |
结论
在 Java 中计算两个有序数组的中位数并不仅是一个简单的任务。通过有效的二分查找方法,我们可以在 O(log(min(n, m))) 的时间复杂度内得到结果。希望通过本文的解析,读者能够对这一问题有更深入的理解,并在实际应用中有效利用这一算法。
















