题目描述
给定两个大小为 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
解决思路1
题目给定的输入是两个list类型,python中的list类型中有一个list.extend()方法,时间复杂度是O(n),可以将两个list类型的列表合并成一个列表,然后对这个新列表进行排序,时间复杂度是O((m+n)log(m+n)),便可以找到中位数了
class Solution:
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
nums1.extend(nums2) //时间复杂度O(n)
nums1.sort() //时间复杂度O((m+n)log(m+n))
n = len(nums1)
if n%2 == 1:
return float(nums1[n//2])
else:
return (nums1[n//2-1]+nums1[n//2])/2.0
结果 104ms
解决思路2
我们可以将两个数组按序排列成一个数组,然后直接取其中位数,时间复杂度O(m+n)
class Solution:
def getmid(self,nums): //处理某个数组为空时的情况
if len(nums)%2 ==0:
return (nums[len(nums)//2]+nums[(len(nums)//2)-1])/2
else:
return nums[len(nums)//2]
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
if len(nums1)==0:
return self.getmid(nums2)
if len(nums2)==0:
return self.getmid(nums1)
nlen=len(nums1)+len(nums2)
i=j=0
temp=[]
while (i<len(nums1) and j<len(nums2)): //为每个数组设立一个指针,将其合并
if nums1[i]<nums2[j]:
temp.append(nums1[i])
i+=1
else:
temp.append(nums2[j])
j+=1
while (i<len(nums1)):
temp.append(nums1[i])
i+=1
while (j<len(nums2)):
temp.append(nums2[j])
j+=1
if nlen%2==0:
return (temp[nlen//2]+temp[nlen//2-1])/2
else:
return temp[nlen//2]
结果 88ms
解决思路3
题目中给出了要求的时间复杂度为O(log(m+n)),我们这里想到的是二分查找,二分查找的时间复杂度为O(logn),首先我们先分析下题目,假设两个有序数组共有n个元素,当n为奇数时,查找第(n//2)个元素,当n为偶数时,查找第(n//2)和第(n//2-1)个元素,然后取他们的均值。
考虑二分查找时的情况,我们希望找到第一个数组中前p个元素和第二个数组中前q个元素,我们想要的最终结果是:p+q等于k-1,这样第p+1个元素或者第q+1个元素就是我们要找的第k个元素。
通过二分法将问题规模缩小,假设p=k//2-1,则q=k-p-1,且p+q=k-1。如果第一个数组第p个元素小于第二个数组第q个元素,我们不确定二数组第q个元素是大了还是小了,但一数组的前p个元素肯定都小于目标,所以我们将第一个数组前p个元素全部抛弃,形成一个较短的新数组。然后,用新数组替代原先的第一个数组,再找其中的第k-p个元素,依次递归。同理,如果第一个数组第p个元素大于第二个数组第q个元素,我们则抛弃第二个数组的前q个元素。当递归遇到k=1时,或者第p个元素=第q个元素时,结束递归。
class Solution:
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
m=len(nums1)
n=len(nums2)
k=(m+n)//2
if (m+n)%2==0: #总长度为偶数
return (self.findk(nums1,nums2,k)+self.findk(nums1,nums2,k-1))/2
else: #总长度为奇数
return self.findk(nums1,nums2,k)
def findk(self,n1,n2,k):
if len(n1)>len(n2): #确保长度最短的数组排在前面
return self.findk(n2,n1,k)
if len(n1)==0:
return n2[k]
if k==1:
if n1[0]<n2[0]:
if len(n1)>1:
return min(n1[1],n2[0])
else:
return n2[0]
else:
if len(n2)>1:
return min(n1[0],n2[1])
else:
return n1[0]
if k==0:
return min(n1[0],n2[0])
p=min(k//2-1,len(n1)-1)
q=k-p-1
if(n1[p]<n2[q]):
return self.findk(n1[p+1:],n2,k-p-1)
elif(n1[p]>n2[q]):
return self.findk(n1,n2[q+1:],k-q-1)
else:
return n1[p]
结果84ms,击败100%