思路:
将问题转换为求两个有序数组的第k项问题, 因为是中位数, 那么就是第(m + n) / 2项. 第k项问题在处理的时候用到二分法的思路, 每次用两个数组的中项相比, 小的一方左边所有元素都可以直接弃掉, 所以每次可以排除k / 2个元素. 时间复杂度为O(logk), 此题为O(log(m + n)).
// 查询两个排序数组第k个元素的函数
double findKth(vector<int>::iterator it1, int n1, vector<int>::it2, int n2, int k) {
if (n1 > n2) // 保证n1比n2短或等于
return findKth(it2, n2, it1, n1, int k);
if (! n1) // 如果第一个数组为空, 则直接返回第二个数组中的元素
return *(it2 + k - 1);
if (k == 1) // 如果k为1, 则直接返回两个数组中较小的首元素
return min(*it1, *it2);
// 将k尽量分为两份, 但因为n1有可能小到不够k的一半, 所以为了避免越界访问数组, 取min
int offset1 = min(k / 2, n1), offset2 = k - offset1;
if (*(it1 + offset1 - 1) < *(it2 + offset2 - 1))
return findKth(it1 + offset1, n1 - offset1, it2, n2, k - offset1);
else if (*(it1 + offset1 - 1) > *(it2 + offset2 - 1))
return findKth(it1, n1, it2 + offset2, n2 - offset2, k - offset2);
else
return *(it1 + offset1 - 1);
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int total = nums1.size() + nums2.size();
if (total & 1)
return findKth(nums1.begin(), nums1.size(), nums2.begin(), nums2.size(), total / 2 + 1);
else
return (findKth(nums1.begin(), nums1.size(), nums2.begin(), nums2.size(), total / 2)
+ findKth(nums1.begin(), nums1.size(), nums2.begin(), nums2.size(), total / 2 + 1))
/ 2.0;
}