给定两个大小为 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
题意分析:
在两个有序数组中寻找中位数,关键要求时间复杂度为0(log(m+n))
在第一次见到这个题的时候,我真是惊呆了,当时我还是个小白,没想到这道题居然能有这么巧妙的解法,光看懂答案就花了不知道多少时间。
思路分析:
我们知道中位数的定义是整个数组的最中间的数,换句话说,以中位数为界,可以将数组分为两个长度相等的部分。关键也就在此,例如对于两个有序数组,一个长度为3,一个长度5,那么我们知道按中位数划分后两边的数组长度应该都为4,并且满足左边数组的最大值要小于等于右边数组的最小值。
根据这个分析,我们只需要找出左边数组的4个数有几个是从第一个数组里面获得的即可。
例如我们假定左边数组的4个数中有i个数
是从第一个数组中获得,那么则有4-i个数
从第二个数组中获得。我们只需要判断 max(nums1[i-1], nums2[4-i-1])
(左边数组的最大值)是否小于等于 min(nums1[i], nums1[4-i])
(右边数组的最小值),如果满足上述式子,则说明我们成功找到了这个分界点,则中位数可求(要根据长度奇偶来分别计算)!
我们在寻找具体的i
的时候使用二分法,由于i
代表的意义为从第一个数组中拿多少数,所以i
的最小值为0
,最大值为 min(n, (m+n)//2)
,所以是满足复杂度为0(log(m+n))这个条件的。
另一个关键点,我们知道二分法需要不停的变换上下界,那么在这里如果不满足上述条件,lo
和hi
应该怎样变化呢?关键在于nums[i-1]
,如果是nums[i-1] > 右边的最小值
,说明我们的i
已经选的太大了,故hi = mid
;反之,则说明我们的i
选的太小了,导致4-i
太大了,故lo = mid + 1
。
当然在具体判断条件时可能会出现数组越界的情况,所以实际写代码的时候需要用到一点技巧来处理!
1 | # 68ms, beats 48.51% |