median-of-two-sorted-arrays
中位数性质:(元素个数为n, 已排序)
- 当
n
为奇数时,中位数是第n/2
个元素 - 当
n
为偶数时,中位数是第n/2
个元素和第n/2+1
个元素的平均值
只有1个数组时,将数组分为2个部分
- 当数组长度为偶数时,中位数有2个:左边数组最大值、右边数组最小值
当数组为奇数时,中位数有1个,我们把中位数分到左边数组
左边数组多一个,中位数在左边数组最大值
有2个数组时,仍可以将2个数组分割为2个部分
我们不用去确定分割线确定分割线在2个数组中的位置,我们计算分割线左边和右边元素的个数即可
要确保交叉小于等于关系
极端情况 1
- 在较短的数组上确定分割线的位置,防止数组越界
极端情况 2
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
if (nums1.length > nums2.length) {
int[] tmp = nums1;
nums1 = nums2;
nums2 = tmp;
}
int m = nums1.length;
int n = nums2.length;
// 分割线左边所有元素的个数: m + (n - m + 1) /2
int totalLeft = (m + n + 1) / 2;
// 在 nums1 的区间 [0, m] 里查找恰当的分割线
// 使得 nums1[i-1] <= nums2[j] && nums2[j-1] <= nums1[i]
int left = 0;
int right = m;
// 循环条件结束的条件为指针重合,即分割线已找到
while (left < right) {
int i = left + (right - left + 1) / 2;
int j = totalLeft - i;
if (nums1[i-1] > nums2[j]) {
// 下一轮区间为 [left, i-1]
right = i - 1;
} else {
// 下一轮区间为 [i, right]
left = i;
}
}
int i = left;
int j = totalLeft -i;
int nums1LeftMax = i == 0 ? Integer.MIN_VALUE : nums1[i-1];
int nums1RightMin = i == m ? Integer.MAX_VALUE : nums1[i];
int num2LeftMax = j == 0 ? Integer.MIN_VALUE : nums2[j-1];
int num2RightMin = j == n ? Integer.MAX_VALUE : nums2[j];
if ((m + n) % 2 == 0) {
return (double) (Math.max(nums1LeftMax, num2LeftMax) + Math.min(nums1RightMin, num2RightMin)) / 2.0;
} else {
return Math.max(nums1LeftMax, num2LeftMax);
}
}
}