题目
- 给两个升序数组,长度分别为 m 和 n,返回两个数组合并之后的中位数
- 要求时间复杂度 log(m+n)
思路
-
双指针,分别指向两个数组的开头,找第 K 小的数
- 合并后数组长度为奇数时,中位数为第 (m+n+1) / 2 小的数
- 为偶数时,中位数为 0.5 * 【第 (m+n+1) / 2 小的数 + (m+n+2) / 2】
-
朴素判断方法为:指针移动 k-1 次后,双指针指向的最小的那个值,时间复杂度 m + n
-
优化:没次移动 k/2
代码
class Solution {
public:
int find(
vector<int>& nums1, int l1,
vector<int>& nums2, int l2,
int k) {
int m = nums1.size();
int n = nums2.size();
int len1 = m - l1;
int len2 = n - l2;
if (len1 > len2) {
return find(nums2, l2, nums1, l1, k);
}
if (len1 == 0) {
return nums2[l2 + k - 1];
}
if (k == 1) {
return min(nums1[l1], nums2[l2]);
}
int new_l1 = min(l1 + k/2 - 1, m-1);
int new_l2 = min(l2 + k/2 - 1, n-1);
if (nums1[new_l1] < nums2[new_l2]) {
return find(nums1, new_l1 + 1, nums2, l2, k - (new_l1 - l1 + 1));
} else {
return find(nums1, l1, nums2, new_l2 + 1, k - (new_l2 - l2 + 1));
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size();
int n = nums2.size();
int left = (m + n + 1) / 2;
int right = (m + n + 2) / 2;
if (m == 0) {
return (nums2[left - 1] + nums2[right -1]) * 0.5;
} if (n == 0) {
return (nums1[left - 1] + nums1[right -1]) * 0.5;
}
return 0.5 * (find(nums1, 0, nums2, 0,left) + find(nums1, 0, nums2, 0, right));
}
};