题目
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)).
You may assume nums1 and nums2 cannot be both empty.
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
题解
这个题算法课作业有过,但是只需要说思路,当时想的是分别对两个数组取中位数之后进行比较决定是向左面还是右面搜索,思路是正确的,不断的divide and conquer。但是实践起来向左和右的边界条件是很杂乱的。不知道如何是好,看了题解,记录一下。
两个数组共同的中位数可以将两个数组合并后的数组分为左右数量相等的两部分,对于两个数组A 和 B分别在i和j位置分,则可以将两个数组分为四个部分
A [ 0 ] ⋯ A [ i − 1 ] ∣ A [ i ] ⋯ A [ m − 1 ] A[0] \cdots A[i-1]|A[i]\cdots A[m-1] A[0]⋯A[i−1]∣A[i]⋯A[m−1]
B [ 0 ] ⋯ B [ j − 1 ] ∣ B [ j ] ⋯ B [ n − 1 ] B[0] \cdots B[j-1]|B[j]\cdots B[n-1] B[0]⋯B[j−1]∣B[j]⋯B[n−1]
要想满足找到中位数,需要有 i + j = m − i + n − j i+j=m-i+n-j i+j=m−i+n−j(两边数字个数相同)且 A [ i − 1 ] < B [ j ] a n d A [ i ] > B [ j − 1 ] A[i-1]<B[j]\ and\ A[i]>B[j-1] A[i−1]<B[j] and A[i]>B[j−1]那么此时当i确定时,j的位置也就唯一确定,此时判断上面的的条件即可,注意要满足 m < n m<n m<n的条件,否则会出现负数,同时对于边界条件若 i = 0 i=0 i=0有:
B [ 0 ] ⋯ B [ j − 1 ] ∣ B [ j ] ⋯ B [ n − 1 ] , A [ 0 ] ⋯ A [ i − 1 ] ∣ A [ i ] ⋯ A [ m − 1 ] B[0] \cdots B[j-1]\ |\ B[j]\cdots B[n-1],A[0] \cdots A[i-1]|A[i]\cdots A[m-1] B[0]⋯B[j−1] ∣ B[j]⋯B[n−1],A[0]⋯A[i−1]∣A[i]⋯A[m−1]
所以中位数的左面可以确定为
B
[
j
−
1
]
B[j-1]
B[j−1],同理
j
=
0
j=0
j=0则左为
A
[
i
−
1
]
A[i-1]
A[i−1],
当
i
=
m
或
j
=
n
i=m或j=n
i=m或j=n时可以确定右面分别是
B
[
j
]
和
A
[
i
]
B[j]和A[i]
B[j]和A[i],考虑
m
+
n
m+n
m+n的奇偶性,可以得到最后的结果。查找i的位置使用二分查找,时间复杂度
O
(
l
o
g
n
)
O(logn)
O(logn)
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
m=len(nums1)
n=len(nums2)
if m>n:
nums1,nums2,m,n=nums2,nums1,n,m #满足m<n
imin,imax=0,m
while imin<=imax:
i=int((imin+imax)/2)#二分查找i的位置
j=int((m+n+1)/2)-i
if(i<m and nums2[j-1]>nums1[i]):#不满足条件则增大i此时j自动减小
imin+=1
elif(i>0 and nums1[i-1]>nums2[j]):#不满足条件则减小i此时j自动增大
imax-=1
else:#找到合适的i和j+边界判别
if i==0:
left=nums2[j-1]
elif j==0:
left=nums1[i-1]
else:
left=max(nums1[i-1],nums2[j-1])
if (m+n)%2!=0:
return left
if i==m:
right=nums2[j]
elif j==n:
right=nums1[i]
else:
right=min(nums1[i],nums2[j])
return float((left+right)/2.0)