news 2026/6/10 15:45:31

寻找两个正序数组的中位数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
寻找两个正序数组的中位数

class Solution {

public:

int getKthElement(const vector<int>& nums1, const vector<int>& nums2, int k) {

int m = nums1.size();

int n = nums2.size();

int index1 = 0, index2 = 0;

while (true) {

// 边界情况

if (index1 == m) {

return nums2[index2 + k - 1];

}

if (index2 == n) {

return nums1[index1 + k - 1];

}

if (k == 1) {

return min(nums1[index1], nums2[index2]);

}

// 正常情况

int newIndex1 = min(index1 + k / 2 - 1, m - 1);

int newIndex2 = min(index2 + k / 2 - 1, n - 1);

int pivot1 = nums1[newIndex1];

int pivot2 = nums2[newIndex2];

if (pivot1 <= pivot2) {

k -= newIndex1 - index1 + 1;

index1 = newIndex1 + 1;

}

else {

k -= newIndex2 - index2 + 1;

index2 = newIndex2 + 1;

}

}

}

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {

int totalLength = nums1.size() + nums2.size();

if (totalLength % 2 == 1) {

return getKthElement(nums1, nums2, (totalLength + 1) / 2);

}

else {

return (getKthElement(nums1, nums2, totalLength / 2) + getKthElement(nums1, nums2, totalLength / 2 + 1)) / 2.0;

}

}

};

使用归并的方式,合并两个有序数组,得到一个大的有序数组。大的有序数组的中间位置的元素,即为中位数。

不需要合并两个有序数组,只要找到中位数的位置即可。由于两个数组的长度已知,因此中位数对应的两个数组的下标之和也是已知的。维护两个指针,初始时分别指向两个数组的下标 0 的位置,每次将指向较小值的指针后移一位(如果一个指针已经到达数组末尾,则只需要移动另一个数组的指针),直到到达中位数的位置。

假设两个有序数组的长度分别为 m 和 n,上述两种思路的复杂度如何?

第一种思路的时间复杂度是 O(m+n),空间复杂度是 O(m+n)。第二种思路虽然可以将空间复杂度降到 O(1),但是时间复杂度仍是 O(m+n)。

如何把时间复杂度降低到 O(log(m+n)) 呢?如果对时间复杂度的要求有 log,通常都需要用到二分查找,这道题也可以通过二分查找实现。

根据中位数的定义,当 m+n 是奇数时,中位数是两个有序数组中的第 (m+n)/2 个元素,当 m+n 是偶数时,中位数是两个有序数组中的第 (m+n)/2 个元素和第 (m+n)/2+1 个元素的平均值。因此,这道题可以转化成寻找两个有序数组中的第 k 小的数,其中 k 为 (m+n)/2 或 (m+n)/2+1。

假设两个有序数组分别是 A 和 B。要找到第 k 个元素,我们可以比较 A[k/2−1] 和 B[k/2−1],其中 / 表示整数除法。由于 A[k/2−1] 和 B[k/2−1] 的前面分别有 A[0..k/2−2] 和 B[0..k/2−2],即 k/2−1 个元素,对于 A[k/2−1] 和 B[k/2−1] 中的较小值,最多只会有 (k/2−1)+(k/2−1)≤k−2 个元素比它小,那么它就不能是第 k 小的数了。

因此我们可以归纳出三种情况:

如果 A[k/2−1]<B[k/2−1],则比 A[k/2−1] 小的数最多只有 A 的前 k/2−1 个数和 B 的前 k/2−1 个数,即比 A[k/2−1] 小的数最多只有 k−2 个,因此 A[k/2−1] 不可能是第 k 个数,A[0] 到 A[k/2−1] 也都不可能是第 k 个数,可以全部排除。

如果 A[k/2−1]>B[k/2−1],则可以排除 B[0] 到 B[k/2−1]。

如果 A[k/2−1]=B[k/2−1],则可以归入第一种情况处理。

可以看到,比较 A[k/2−1] 和 B[k/2−1] 之后,可以排除 k/2 个不可能是第 k 小的数,查找范围缩小了一半。同时,我们将在排除后的新数组上继续进行二分查找,并且根据我们排除数的个数,减少 k 的值,这是因为我们排除的数都不大于第 k 小的数。

有以下三种情况需要特殊处理:

如果 A[k/2−1] 或者 B[k/2−1] 越界,那么我们可以选取对应数组中的最后一个元素。在这种情况下,我们必须根据排除数的个数减少 k 的值,而不能直接将 k 减去 k/2。

如果一个数组为空,说明该数组中的所有元素都被排除,我们可以直接返回另一个数组中第 k 小的元素。

如果 k=1,我们只要返回两个数组首元素的最小值即可。

用一个例子说明上述算法。假设两个有序数组如下:

A: 1 3 4 9
B: 1 2 3 4 5 6 7 8 9
两个有序数组的长度分别是 4 和 9,长度之和是 13,中位数是两个有序数组中的第 7 个元素,因此需要找到第 k=7 个元素。

比较两个有序数组中下标为 k/2−1=2 的数,即 A[2] 和 B[2],如下面所示:

A: 1 3 4 9

B: 1 2 3 4 5 6 7 8 9

由于 A[2]>B[2],因此排除 B[0] 到 B[2],即数组 B 的下标偏移(offset)变为 3,同时更新 k 的值:k=k−k/2=4。

下一步寻找,比较两个有序数组中下标为 k/2−1=1 的数,即 A[1] 和 B[4],如下面所示,其中方括号部分表示已经被排除的数。

A: 1 3 4 9

B: [1 2 3] 4 5 6 7 8 9

由于 A[1]<B[4],因此排除 A[0] 到 A[1],即数组 A 的下标偏移变为 2,同时更新 k 的值:k=k−k/2=2。

下一步寻找,比较两个有序数组中下标为 k/2−1=0 的数,即比较 A[2] 和 B[3],如下面所示,其中方括号部分表示已经被排除的数。

A: [1 3] 4 9

B: [1 2 3] 4 5 6 7 8 9

由于 A[2]=B[3],根据之前的规则,排除 A 中的元素,因此排除 A[2],即数组 A 的下标偏移变为 3,同时更新 k 的值: k=k−k/2=1。

由于 k 的值变成 1,因此比较两个有序数组中的未排除下标范围内的第一个数,其中较小的数即为第 k 个数,由于 A[3]>B[3],因此第 k 个数是 B[3]=4。

A: [1 3 4] 9

B: [1 2 3] 4 5 6 7 8 9

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 4:33:01

好写作AI:在创意写作课里,我是工具、伙伴,还是“灵感外挂”?

当一位创意写作课的老师发现&#xff0c;班上最内向的学生因为和AI讨论剧情而眼睛发亮时&#xff0c;她意识到&#xff0c;关于AI角色的争论或许该换个问法了。 深夜的创作工作坊里&#xff0c;大三学生小陈对着“科幻爱情”的命题抓耳挠腮。她打开好写作AI&#xff0c;输入了第…

作者头像 李华
网站建设 2026/6/10 11:07:23

好写作AI:媒体小编的“赛博外挂”,真能让007变摸鱼?

深夜的编辑部&#xff0c;小编小王第8次改稿&#xff0c;领导第3次说“差点意思”。他叹了口气&#xff0c;默默点开了一个名叫“好写作AI”的图标。十分钟后&#xff0c;一篇结构清晰、数据翔实、标题吸睛的初稿生成&#xff0c;而小王刚刚泡好的咖啡&#xff0c;甚至还没凉。…

作者头像 李华
网站建设 2026/6/9 19:53:07

如何快速批量下载B站视频:贝贝BiliBili工具完整使用指南

如何快速批量下载B站视频&#xff1a;贝贝BiliBili工具完整使用指南 【免费下载链接】贝贝BiliBili-B站视频下载 贝贝BiliBili是一款专为B站视频下载设计的PC工具&#xff0c;功能强大且操作简便。它支持批量下载&#xff0c;显著提升下载效率&#xff0c;尤其适合需要大量保存…

作者头像 李华
网站建设 2026/6/9 22:16:18

300M参数撬动千亿市场:EmbeddingGemma开启边缘AI普惠时代

300M参数撬动千亿市场&#xff1a;EmbeddingGemma开启边缘AI普惠时代 【免费下载链接】embeddinggemma-300m-qat-q8_0-unquantized 项目地址: https://ai.gitcode.com/hf_mirrors/unsloth/embeddinggemma-300m-qat-q8_0-unquantized 导语 Google推出的300M参数轻量级嵌…

作者头像 李华
网站建设 2026/6/10 6:06:01

OpenSpec认证Qwen3-VL-30B为合规AI组件

OpenSpec认证Qwen3-VL-30B为合规AI组件 在智能系统日益渗透企业核心业务的今天&#xff0c;一个关键问题摆在架构师面前&#xff1a;如何让前沿AI能力真正“落地”&#xff1f;实验室里的大模型或许能惊艳一时&#xff0c;但进入生产环境后&#xff0c;往往面临接口混乱、行为不…

作者头像 李华