class Solution {
public:
// 主函数:寻找两个有序数组的中位数
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int total = nums1.size() + nums2.size(); // 计算两个数组的总长度
if (total % 2 == 0) { // 总长度为偶数,中位数为中间两个数的平均值
// 查找第 total/2 小的元素(左中位数)
int left = findKthNumber(nums1, 0, nums2, 0, total / 2);
// 查找第 total/2 +1 小的元素(右中位数)
int right = findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
return (left + right) / 2.0; // 返回平均值
} else { // 总长度为奇数,中位数为中间的数
return findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
}
}
// 辅助函数:在两个有序数组中查找第k小的元素(递归实现)
// 参数说明:i 和 j 分别为nums1和nums2的当前查找起始位置
int findKthNumber(vector<int> &nums1, int i, vector<int> &nums2, int j, int k) {
// 保证nums1为较短的数组,减少递归情况(简化后续操作)
if (nums1.size() - i > nums2.size() - j)
return findKthNumber(nums2, j, nums1, i, k);
// 边界情况1:nums1已全部排除,直接在nums2中找第k小元素
if (i == nums1.size())
return nums2[j + k - 1];
// 边界情况2:k=1时,返回两个数组当前起始位置的最小值
if (k == 1)
return min(nums1[i], nums2[j]);
// 确定两个数组的"比较位置",用于排除不可能的部分
// si:nums1中从i开始的第k/2个元素的位置,但不能超过数组长度
int si = min(i + k / 2, int(nums1.size()));
// sj:nums2中从j开始的第k/2个元素的位置
int sj = j + k / 2;
// 比较nums1[si-1]和nums2[sj-1]的大小,排除较小者的前部分
if (nums1[si - 1] > nums2[sj - 1]) {
// nums2的前k/2个元素可以排除,j移动到sj,同时k减少排除的数量k/2
return findKthNumber(nums1, i, nums2, sj, k - k / 2);
} else {
// nums1的前(si - i)个元素可以排除,i移动到si,k减少实际排除的数量(si - i)
return findKthNumber(nums1, si, nums2, j, k - (si - i));
}
}
};
/
算法思路:
1. 中位数问题转化为寻找第k小元素的问题。总长度奇偶情况分别处理。
2. 使用递归法每次排除一定不可能的区域,逐步缩小k的值:
- 每次比较两个数组的第k/2个元素(若存在),较小的数组前k/2个元素不可能包含第k小元素。
- 排除后,更新k值和起始位置,递归处理剩余部分。
3. 关键点:
- 保证nums1为较短的数组,简化边界处理。
- 处理数组长度不足k/2的情况,此时取实际剩余长度。
- 递归终止条件:当其中一个数组被完全排除或k=1时直接处理。
时间复杂度:O(log(m + n)),每次递归k值减少一半。
/