给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
思路一
对于这样的题很自然的想法是:先合并,再求中位数。可是仔细想想似乎不满足题干对时间复杂度的要求,因为合并所需要的时间是O(N)
,其中N = m + n
,且在空间上也会有额外的消耗。显然这不是最优的解法。(不过后来翻评论发现有哥们这样做,而且基本都过了???)
解法一
可以参考归并排序的merge
部分,这里就不做探讨了。
思路二
很惭愧,翻了题解~
值得一说的是,笔者发现官方对这道题的解法数学味有点浓,于是花了点时间研究了一波,下面是一些收获:
先明确一下概念:中位数把一组有序的数列划分成两个数量级相当的子集,左子集恒小于等于右子集。
什么意思呢?翻译成伪代码就是:
COUNT(Left) == COUNT(Right)
;ANY(Left) <= ANY(Right)
;
咋一看好像没什么卵用,仔细一想其实不然,这个概念是可逆的,也就是说:如果某个数满足这个概念,则其就是要找的中位数。
那么不妨假设在第一个有序数集A
中找到了一个下标为x
的数把A
划分为等量的两份,在数集B
中找到的划分点下标为y
,画图形象化就是:
|
A[0]...A[x-1] | A[x]...A[m-1]
B[0],B[1]...B[y-1] | B[y],B[y+1]