§1
题目描述
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2 。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O(log (m+n)) 。
nums1, nums2 = [1,2], [3,4,5,6]
输出 = 3.5
§2
思路解析动画文字版
下面 9 步动画会按主解代码推进,而不是泛泛讲题型。
① 目标·不合并就找中位数:不真合并:在两数组上「切一刀」就能定位中位。
② 核心·在两数组各切一刀:左半凑够一半、且左半都≤右半 —— 这刀就切对了。
③ 二分·只在短数组 [1,2] 上找切点 i:切点只在短数组上找,另一刀由「左半总数固定」反推。
④ 检查 i=1:切偏了 → i 往右挪:交叉条件不满足:左半有数比右半大 → 朝违规方向挪切点。
⑤ 检查 i=2:切对了:两个交叉条件都满足 → 命中正确切分。
⑥ 取中位数·看切口两侧:奇数取左半最大;偶数取「左半最大+右半最小」的一半。
记住这题的代码骨架:题意约束先落到状态变量,再用循环或递归维护它。
迁移阶梯:把这题练到能复述后,再去同类题里迁移:先复用状态定义,再调整边界条件。
边界三连:边界三连:极端输入先过一遍。
几个高频追问,记住答法。
§3
参考代码
class Solution: def findMedianSortedArrays(self, nums1, nums2): if len(nums1) > len(nums2): nums1, nums2 = nums2, nums1 m = len(nums1) n = len(nums2) half = (m + n + 1) // 2 l = 0 r = m while l <= r: i = (l + r) // 2 j = half - i left1 = nums1[i - 1] if i > 0 else float('-inf') right1 = nums1[i] if i < m else float('inf') left2 = nums2[j - 1] if j > 0 else float('-inf') right2 = nums2[j] if j < n else float('inf') if left1 <= right2 and left2 <= right1: if (m + n) % 2: return max(left1, left2) return (max(left1, left2) + min(right1, right2)) / 2 if left1 > right2: r = i - 1 else: l = i + 1看懂代码不等于写得出。盖住上面,自己默写一遍试试。卡在哪一行说不清,就点右下角问小欧。
§4
复杂度
- 时间复杂度:O(log min(m,n)),只在短数组二分
- 空间复杂度:O(1),只用边界变量
§5
易错点
✗ 错误写法:在长数组二分
✓ 正确写法:确保 nums1 更短
切分点边界更好处理
✗ 错误写法:奇偶长度统一错误
✓ 正确写法:奇数取左半最大,偶数取两侧平均
中位数定义不同
§
面试追问把动画讲成自己的话
追问为什么在「较短」数组上二分?
切点范围 0..短数组长,二分次数 O(log min(m,n)) 更少,且另一刀 j 不会越界。
追问总长奇偶怎么取中位数?
奇数取左半最大;偶数取(左半最大+右半最小)/2。左半固定为 (m+n+1)/2 保证奇数时多一个在左。
追问切到数组头/尾的边界怎么处理?
切点在端点时,用 ±∞ 兜住越界的 nums1[i-1] 或 nums2[j],让交叉条件恒成立、不用特判。
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
下一题 · 二分查找 8/10
→查找元素的首末位置
LeetCode 34 · 中等 · 沿着 二分查找 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
299道动画图解
37节语音讲解
28课数据结构
¥0.27折合 / 天
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
¥99 开通年卡 →
想成体系刷透这类套路?去图解算法专题