这是 LeetCode 上的一道题,求两个有序数组的中位数:
https://leetcode.com/problems/median-of-two-sorted-arrays/description/
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
Example 1:
nums1 = [1, 3]
nums2 = [2]The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]The median is (2 + 3)/2 = 2.5
这道题初看并不复杂,很容易想到时间复杂度为
很多中文博客都是用的寻找第
首先确定一下输入应满足的条件:两个数组可以有一个数组的长度为 0(此时中位数就是另一个数组的中位数),但长度不能同时为 0,因为此时不存在中位数。
划分
设两个数组中位数为
其中
这里先不关注
如果同时满足以下两个条件:
-
-
左边最大的元素
,右边最小的元素
则找到了划分位置,并且
由此,问题转化为:查找这样的
根据第一个条件,由
1 |
j = (m + n + 1) / 2 - i; |
以上表达式在
第二个条件等价于:
二分查找
的取值范围
现考察
显然
即可保证
-
当
为偶数时, ,则 -
当
为奇数时, ,则 ,又 、 必为一奇一偶,因此
综合得
因此只需
在编程实现时,就要先比较两个数组长度,如果
查找思路
要在
初始情况下,令
1 |
int begin = 0, end = m; |
然后令
1 |
i = begin + (end - begin) / 2; |
如果m == 0
,此时相当于只对
如果m != 0
,就要判断上面第二个条件是否成立,成立则找到所求划分位置,否则就舍去
但是在
我这里给出的方法比较笨,分为如下三种情形,如果你有更好的方法欢迎讨论:
-
时 不存在,相当于把数组 的所有元素划分到右边,只需判断 是否成立即可。 但
是否存在,也就是说是否一定有 呢?答案是肯定的。显然 ,注意到 是一个恒定的正数 (m + n + 1) / 2
,因此, 。 这样,
- 若
,说明 太小, 的最终位置应在 之中,此时就应舍去一半元素:
1
begin = i + 1;
- 否则说明找到
- 若
-
时, 在 、 处分别取 、 ,则 。 此时两个不等式中的元素均存在,并且
-
若
,说明 太小, 太大,应: 1
end = i - 1;
-
若
,说明 太小,应: 1
begin = i + 1;
-
否则说明找到
-
-
时 不存在,只需判断 是否成立即可。显然 必存在,又 ,故 也必存在。 在这种情况下,
-
若
,说明 太大,应: 1
end = i - 1;
-
否则说明找到
-
这样,通过二分查找,找到所需要的
计算中位数
现在已经找出了划分位置,如果共有奇数个元素,则中位数为左边元素的最大值,如果共有偶数个元素,则中位数为左边最大值和右边最小值的平均数。
-
若
不存在,即 ,左边最大值即为 ( 为确定的正数 (m + n + 1) / 2
,故, 必定存在) -
若
不存在,即 ,左边最大值即为 (同样 必定存在) -
若
、 均存在时,左边最大值为
如果
时间复杂度
此算法相当于在长度为
实现源码
https://github.com/qianbinbin/leetcode
近期评论