java练习(34)
ps:题目来自力扣
寻找两个正序数组的中位数
给定两个大小分别为 m
和 n
的正序(从小到大)数组 nums1
和 nums2
。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n))
。
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
// 为了让二分查找的范围更小,保证 nums1 是较短的数组
if (nums1.length > nums2.length) {
int[] temp = nums1;
nums1 = nums2;
nums2 = temp;
}
int m = nums1.length;
int n = nums2.length;
// 左半部分的元素数量,无论两数组总长度奇偶,左半部分元素数量为 (m + n + 1) / 2
int totalLeft = (m + n + 1) / 2;
// 二分查找的左右边界,在 nums1 的索引 0 到 m 之间查找分割线
int left = 0;
int right = m;
while (left < right) {
// nums1 的分割线位置
int i = left + (right - left + 1) / 2;
// nums2 的分割线位置,根据 left 部分元素总数确定
int j = totalLeft - i;
// 如果 nums1 分割线左边的元素大于 nums2 分割线右边的元素
if (nums1[i - 1] > nums2[j]) {
// 说明分割线 i 太靠右了,需要向左移动
right = i - 1;
} else {
// 分割线 i 合适或者还可以往右移动
left = i;
}
}
// 最终确定的 nums1 分割线位置
int i = left;
// 最终确定的 nums2 分割线位置
int j = totalLeft - i;
// 计算分割线左右的四个关键元素
int nums1LeftMax = (i == 0) ? Integer.MIN_VALUE : nums1[i - 1];
int nums1RightMin = (i == m) ? Integer.MAX_VALUE : nums1[i];
int nums2LeftMax = (j == 0) ? Integer.MIN_VALUE : nums2[j - 1];
int nums2RightMin = (j == n) ? Integer.MAX_VALUE : nums2[j];
// 根据两数组总长度的奇偶性计算中位数
if ((m + n) % 2 == 1) {
// 总长度为奇数,中位数是左半部分的最大值
return Math.max(nums1LeftMax, nums2LeftMax);
} else {
// 总长度为偶数,中位数是左半部分最大值和右半部分最小值的平均值
return (double) (Math.max(nums1LeftMax, nums2LeftMax) + Math.min(nums1RightMin, nums2RightMin)) / 2;
}
}
}