有两个分别为大小m和n的排序数组nums1和nums2。
找到两个排序数组的中位数。总体运行时复杂度应为O(log(n+m))。 假设nums1和nums2不能都为空。
nums1 | nums2 | Median | |
---|---|---|---|
A | [2] | [] | 2 |
B | [3] | [-2,-1] | -1 |
C | [1,3,4] | [-2,5,6] | 3.5 |
题中的中位数是相当于把nums1和nums2合并之后从小到大排序中间的数, 不考虑时间复杂度可以用sort函数自检:
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
res = sorted(nums1 + nums2)
l = len(res)//2
if len(res)%2==1:
return res[l]
else:
return (res[l] + res[l- 1])/2
中位数就是如果两个list大小之和为奇数则取中间的数, 否则就取中间两个数加和除2。
运用到两个list中就是把nums1和nums2分成两部分其中第一部分的最大值小于第二部分的最小值
二分法: 首先要知道两个list长度和合并之后中位数所在位置。{l1=len(nums1); l2=len(nums2); l=(l1+l2+1)//2}
选取两个list中长度小的(nums1)进行操作, 设置一个min_index初始值为0, max_index初始值为小的list的长度。对nums1进行分区, 用i表示刚开始在nums1中间的位置,j则表示中位数前半部分选取了i个属于nums1的数字后, 剩余数字即属于nums2的数量。
{if l1>l2: nums1,nums2,l1,l2=nums2,nums1,l2,l1
min_index,max_index=0,l1
while min_index<=max_index:
i=(min_index+max_index)//2
j=l-i}
考虑到当i=l1时,nums1的后半部分则为空,且如果j=0时,则nums2的前半部分则为空,所以要比较一下两个list中的元素从右侧进行操作;如果i=0,j=l2则表示nums1的前半部分为空,nums2的后半部分为空,所以需要比较两个list元素大小从左侧进行操作。此外nums1或者nums2可能为空,所以要返回不为空的中间的值;都满足要求即左侧的最大值小于等于右侧的最小值则把左侧的最大值付给median变量。
{if i<l1 and j>0 and nums1[i]<nums2[j-1]: min_index+=1
elif i>0 and j<l2 and nums1[i-1]>nums2[j]: max_index-=1
else: if i==0: median=nums2[j-1]
elif j==0: median=nums1[i-1]
else: median=max(nums1[i-1], nums2[j-1])}
到现在为止已经找到中位数的位置,开始判断l1+l2是奇数还是偶数,如果是奇数,则返回median,如果是偶数数则返回median+右侧nums1和nums2的最小值加和除2,如果i=l1则nums1没有右侧部分所以返回median+nums2的右侧除2,j=l2同理。
{if (l1+l2)%2==1: return median
elif i==l1: return (median+nums2[j])/2
elif j==l2: return (median+nums1[i])/2
else: return (median+min(nums1[i],nums2[j]))/2}
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
l1=len(nums1)
l2=len(nums2)
if l1>l2:
nums1,nums2,l1,l2=nums2,nums1,l2,l1
l=(l1+l2+1)//2
min_index=0
max_index=l1
while min_index<=max_index:
i=(min_index+max_index)//2
j=l-i
if i<l1 and j>0 and nums2[j-1]>nums1[i]:
min_index=i+1
elif i>0 and j<l2 and nums1[i-1]>nums2[j]:
max_index=i-1
else:
if i==0:
median=nums2[j-1]
elif j==0: #例如nums1=[1,2] nums2=[3,4]
median=nums1[i-1]
else:
median=max(nums1[i-1],nums2[j-1])
if (l1+l2)%2==1:
return median
elif i==l1:
return (median+nums2[j])/2
elif j==l2:
return (median+nums1[i])/2
else:
return (median+min(nums2[j],nums1[i]))/2
时间复杂度O(log(min(n,m)))因为是对两个list中size小的进行操作。