Description
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.
Difficulty
Hard
Example1
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example2
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
Solution
public class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int sumLen = nums1.length + nums2.length;
if (sumLen % 2 == 0) {
return (findKthSortedArrays(nums1, 0, nums2, 0, sumLen / 2 + 1) +
findKthSortedArrays(nums1, 0, nums2, 0, sumLen / 2)) / 2.0;
}
return findKthSortedArrays(nums1, 0, nums2, 0, sumLen / 2 + 1);
}
//用于查找nums1、nums2两个数组中第K小的数,其中K从1开始算
private int findKthSortedArrays(int[] nums1, int startIdx1, int[] nums2, int startIdx2, int k) {
//情况1:数组nums1整体都小于nums1和nums2两个数组中的第K个数
if (startIdx1 >= nums1.length) {
return nums2[startIdx2 + k - 1];
}
//情况2:数组nums2整体都小于nums1和nums2两个数组中的第K个数
if (startIdx2 >= nums2.length) {
return nums1[startIdx1 + k - 1];
}
//情况3:找出num1和nums2中最小的数(即k == 1)
if (k == 1) return Math.min(nums1[startIdx1], nums2[startIdx2]);
//根据二分查找的特性,找出nums1数组在startIdx1和nums1.length - 1范围内的第 k / 2 个数(即nums1[startIdx1 + k / 2 - 1])
//同理找出nums2数组在给定范围内的第 k / 2 个数(即nums2[startIdx2 + k / 2 - 1])
//当数组nums1和nums2在给定范围内,不存在第 k / 2 个数,或者nums1和nums2中第 k / 2 个数更大的一方,不缩小其查找范围
int halfNums1 = startIdx1 + k / 2 - 1 < nums1.length ? nums1[startIdx1 + k / 2 - 1] : Integer.MAX_VALUE;
int halfNums2 = startIdx2 + k / 2 - 1 < nums2.length ? nums2[startIdx2 + k / 2 - 1] : Integer.MAX_VALUE;
//缩小nums1和nums2二个数组中,第 startIdx + k / 2 - 1 更小一方的查找范围,缩小至:startIdx + k / 2 ~ endIdx。
//k 则变为 k - k / 2;
if (halfNums1 > halfNums2) {
return findKthSortedArrays(nums1, startIdx1, nums2, startIdx2 + k / 2, k - k / 2);
} else {
return findKthSortedArrays(nums1, startIdx1 + k / 2, nums2, startIdx2, k - k / 2);
}
}
}
Summary
- findKthSortedArrays方法中的参数 k ,并不是索引,而是索引 + 1
- 核心思想:利用二分查找,每次将双数组的范围缩小 k / 2
- 范围缩小过程中,时刻注意二分查找是边界值的设定