LeetCode上的一道题目,有点意思,求两有序数组放一块以后的中位数,复杂度要求O(log(n+m))
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
我们知道如果是一个无序数组,找中位数复杂度可以在O(log(n))。而一个有序数组求他中位数基本就是O(1)。
现在是两个有序数组,结合二分的思路稍微要用点技巧,我的做法可以叫做二分排除法。
我们要求两数组合并后那个中间的一个数或两个数,即取第K小值问题。
上图中a到c和d到f都是有序的,ab和de长都为k/2。如果b处的数比e处的数小,说明什么,说明那个第K小的数一定不在ab之间,把ab裁掉拿bc重复操作,最终就能找到中位数。
以下是Python的实现。实现过程中还要注意一点,如果是用C/C++写的话,递归时候直接数组头一跳就变成新参数了。而Python中的切片操作本身复杂度是O(k)的,所以我采用index后跳的方式,模仿C里的数组头后跳。还有len()方法是O(1)的,可以大胆用。
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
k_1 = (len(nums1) + len(nums2)+1)/2
k_2 = (len(nums1) + len(nums2)+2)/2
med_1 = self.search_k_th(nums1, 0, nums2, 0, k_1)
med_2 = self.search_k_th(nums1, 0, nums2, 0, k_2)
return (med_1 + med_2)/2.0
def search_k_th(self, nums_1, head_1, nums_2, head_2, k):
if head_1 == len(nums_1):
return nums_2[head_2+k-1]
elif head_2 == len(nums_2):
return nums_1[head_1+k-1]
elif k == 1:
return min(nums_1[head_1], nums_2[head_2])
step_1 = min(k/2, len(nums_1)-head_1)
step_2 = min(k/2, len(nums_2)-head_2)
if nums_1[head_1+step_1-1] < nums_2[head_2+step_2-1]:
return self.search_k_th(nums_1, head_1+step_1, nums_2, head_2, k-step_1)
else:
return self.search_k_th(nums_1, head_1, nums_2, head_2+step_2, k-step_2)
这道题也提醒我应该关注一下Python内置函数的复杂度。Python Wiki上有