法1:二分查找(最优解法)
时间复杂度:O(logMin(m, n)),空间复杂度:O(1)。
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, n = nums2.length;
// 在nums1的区间[0, m]里查找恰当的分割线
// 使得nums1[i - 1] ≤ nums2[j] && nums2[j - 1] ≤ nums1[i]
int totalLeft = (m + n + 1) / 2; // 左 ≥ 右
int left = 0, right = m; // [left, right)是闭开区间
while (left < right) {
int nums1Left = (left + right + 1) / 2; // 是指的nums1分割线左侧元素个数(左 ≥ 右), 对应索引是nums1Left - 1
int nums2Left = totalLeft - nums1Left; // 是指的nums2分割线左侧元素个数(左 ≥ 右), 对应索引是nums2Left - 1
if (nums1[nums1Left - 1] > nums2[nums2Left]) { // nums1的分割线太靠右,需要往左移
right = nums1Left - 1; // right是取不到的边界, 下次迭代索引nums1Left - 1肯定取不到,故设置right = nums1Left - 1
} else { // 这里并未直接判断nums2[nums2Left - 1]与nums1[nums1Left]的关系, 故使得nums1[nums1Left]尽量大
left = nums1Left; // left是可取到的边界, 下次迭代索引可能取到nums1Left,故设置left = nums1Left
}
}
int i = left, j = totalLeft - left;
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];
int leftMax = Math.max(nums1LeftMax, nums2LeftMax);
int rightMin = Math.min(nums1RightMin, nums2RightMin);
if ((m + n) % 2 == 1) {
return (double) leftMax;
} else {
return ((double) leftMax + (double) rightMin) / 2.0;
}
}
}