寻找两个有序数组的中位数。
给定两个大小为 m 和 n 的有序数组 nums1
和 nums2
。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1
和 nums2
不会同时为空。
示例 1:
1 |
|
示例 2:
1 |
|
思路一
找两个有序数组的中位数,实际上就是找到两个数组中第 $\frac{m + n}{2}$ 大的数。找到两个有序数组 $a, b$ 中第 $k$(从0计起) 大的数的流程如下:
- 当 $a$ 或 $b$ 为空时,直接返回 $b[k]$ 或 $a[k]$;
- 分别取 $a$ 和 $b$ 的中位数 $m_a$ 和 $m_b$,以及对应下标 $l_a$ 和 $l_b$;
- 当 $l_a + l_b < k$ 时,说明 $a$ 和 $b$ 中其中一个数组的左边一半不含第 $k$ 个数,如果$m_a < m_b$,说明 $a$ 的左边一半(包含$a[l_a]$)不含第 $k$ 个数,即可以剔除 $l_a + 1$ 个数,然后在有序数组 $a[l_a+1:]$ 和 $b$ 中寻找第 $k-l_a-1$ 大的数;如果 $m_a \ge m_b$,说明 $b$ 的左边一半(包含$b[l_b]$)不含第 $k$ 个数,即可以剔除 $l_b + 1$ 个数,然后在有序数组 $a$ 和 $b[l_b+1:]$ 中寻找第 $k-l_b-1$ 大的数;
- 当 $l_a + l_b \ge k$ 时,说明 $a$ 和 $b$ 中其中一个数组的右边一半不含第 $k$ 个数,如果$m_a < m_b$,说明 $b$ 的右边一半不含第 $k$ 个数,即可以剔除 $l_b$ 个数,然后在有序数组 $a$ 和 $b[:l_b]$ 中寻找第 $k$ 大的数;如果 $m_a \ge m_b$,说明 $a$ 的右边一半不含第 $k$ 个数,即可以剔除 $l_a$ 个数,然后在有序数组 $a[:l_a]$ 和 $b$ 中寻找第 $k$ 大的数。
1 |
|
思路二
假设 $m < n$,我们可以将两个有序数组A
和B
都划分成两个部分,如下所示:
1 |
|
如果我们可以保证:
1 |
|
那么我们就可以得到中位数 \(median = \frac{\max(left\_part) + \min(right\_part)}{2}\)。
为了满足上述两个条件,我们必须保证:
1 |
|
然后使用二分搜索在 [0, m]
中寻找合适的i
:
1 |
|
代码如下:
1 |
|