题目链接
4. 寻找两个正序数组的中位数 - 力扣(LeetCode)
实现思路
- **本质上,其实就是求两个数组第k大的数的变式。**设两个数组大小为m、n,则总长度为t=m+n,那么如果t为奇数,求的就是两个数组第t/2+1大的数;如果t为偶数,求的就是两个数组第t/2和第t/2+1大的数的平均数。
- 那么,求两个数组第k大的数,每次判断当前数组第k/2大的数的大小关系,如果数组1对应的位置aj小于数组2对应位置bj的元素,那么aj连同之前的数字,必然不可能是第k大的数!这样的话,就移动数组1的开始下标,并且k减去k/2,再次计算当前开始下标的条件下,两个数组第k(其实就是上一次的k-k/2)大的元素。
可以大致看一下下面的图解:

代码实现
cpp
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size();
int n = nums2.size();
int t = m + n;
if (t % 2) {
return find(nums1, 0, m - 1, nums2, 0, n - 1, t / 2 + 1);
} else {
return (find(nums1, 0, m - 1, nums2, 0, n - 1, t / 2) +
find(nums1, 0, m - 1, nums2, 0, n - 1, t / 2 + 1)) / 2.0;
}
}
// 找到两个数组中合并后第k大的数
int find(vector<int>& nums1, int astart, int aend, vector<int>& nums2, int bstart, int bend, int k) {
if (astart > aend) {
return nums2[bstart + k - 1];
}
if (bstart > bend) {
return nums1[astart + k - 1];
}
if (k == 1) {
return min(nums1[astart], nums2[bstart]);
}
int q = k / 2;
// 注意边界判断
int aj = min(astart + q - 1, aend);
int bj = min(bstart + q - 1, bend);
if (nums1[aj] <= nums2[bj]) {
return find(nums1, aj + 1, aend, nums2, bstart, bend, k - (aj - astart + 1));
} else {
return find(nums1, astart, aend, nums2, bj + 1, bend, k - (bj - bstart + 1));
}
}
};