不能直接合并再取中位数,因违背O(log(m+n))时间复杂度要求;核心是转化为找第k小元素,用二分排除法,需严谨处理空数组、k=1、索引越界及偶数长度时的双k调用与double转换。

为什么不能直接合并再取中位数
能合并当然可以,但题目隐含要求 O(log(m+n)) 时间复杂度,合并本身就要 O(m+n),直接出局。核心思路是把「找中位数」转化为「找第 k 小元素」,再用二分排除——每次比较两个数组的第 k/2 个元素,小的那一侧前 k/2 个数全可安全舍弃。
findKthElement 的边界处理细节
递归找第 k 小时,常见崩溃点在索引越界和 k=1 的终止条件。必须提前判断:
- 若某数组已空(起始索引超出长度),直接返回另一数组的第 k 个元素(注意:索引是
start + k - 1) - 若
k == 1,直接返回两个数组当前首元素的较小值 - 取
mid位置时,不能硬写index = start + k/2 - 1,要先检查start + k/2 - 1是否越界;越界就取该数组末尾元素,同时调整实际比较的「有效 k 段长度」
示例:数组 A = [1,3],当前 startA = 0,想取第 k=3 小,k/2 = 1,则 midA = 0 + 1 - 1 = 0,合法;但若 k=5,0 + 2 - 1 = 1 仍合法;若 A = [1] 且 k=3,0 + 1 - 1 = 0 是唯一可用位置。
偶数总长度时的中位数计算陷阱
总长 m + n 为偶数时,中位数是「第 (m+n)/2 小」和「第 (m+n)/2 + 1 小」的平均值。注意不是 (m+n+1)/2 和 (m+n+2)/2 —— 那在奇数时会重复取同一个位置。正确对应关系是:
立即学习“C++免费学习笔记(深入)”;
- 第 1 小 → 索引 0
- 第 k 小 → 实际取的是排序后下标为
k-1的值 - 所以偶数长度
L下,要调用两次findKthElement:一次k = L/2,一次k = L/2 + 1
例如 [1,2] 和 [3,4],总长 4,需取第 2 小(值为 2)和第 3 小(值为 3),结果为 (2+3)/2.0 = 2.5。
整数除法与类型转换的隐蔽问题
返回值是 double,但所有中间计算用的是 int 索引和 int 值。最容易漏的是最后平均时没转 double:
// 错误:整数除法截断 return (left + right) / 2; // 若 left=2, right=3 → 结果是 2 <p>// 正确:至少一侧转 double return (left + right) / 2.0; // 或 return (static_cast<double>(left) + right) / 2;</p>
另外,k/2 在 C++ 里是向下取整(如 3/2=1),这恰好符合我们“舍弃前 k/2 个”的需求,无需额外 floor,但得意识到它不是四舍五入。
中位数本身不难理解,难的是在不破坏对数时间前提下把边界条件全兜住——尤其是空数组、k 超出单数组长度、以及偶数长度下两个 k 值的精确对应。这些地方错一个,结果就完全不对。


















