解法
假如我们把A
分成A[:i]
和A[i:]
两部分,同理把B
分成B[:j]
和B[j:]
两部分
我们让A[:i]+B[:j]
归为左边,A[i:]+B[j:]
归为右边
如果:
- 左边和右边数字的个数相差不超过1
- 左边的数字全比右边小
那么中位数将在左边的最大值和右边的最小值之间产生。
不妨令左边总是数量少的那方,即左边要么比右边少1,要么与右边相等。
很容易可以计算出,i+j==(m+n)//2
所以我们只需要搜索i或j其中一方即可。
对于满足上述条件的(i,j)
,我们还要让它满足条件2,那就需要:
A[i-1]<=B[j]
且B[j-1]<=A[i]
为了方便查找,我们总是假设m<=n,然后从0到m二分搜索i的值,搜索小的的好处是,由于在二分查找的过程中i不可能等于m,所以j也一定会在
(
0
,
n
)
(0,n)
(0,n)范围内,这说明B[j-1]
和B[j]
都是有效的,省下了一次边界条件的判断。
查找的过程中如何移动呢?
首先很明显A[i-1]>B[j]
和B[j-1]>A[i]
是互斥的
- 如果
A[i-1]>B[j]
,说明i太大了,要向小了搜 - 如果
B[j-1]>A[i]
,说明i太小了,要向大了搜
最后就是要注意边界条件的判断
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
if len(nums1)>len(nums2):
nums1,nums2 = nums2,nums1
m,n = len(nums1),len(nums2)
odd = (m+n)%2!=0
tar = (m+n)>>1
l,r = 0,m
def solve(i):
j = tar-i
if i==m:
up = nums2[j]
elif j==n:
up = nums1[i]
else:
up = min(nums2[j],nums1[i])
if odd:
return up
if j==0:
down = nums1[i-1]
elif i==0:
down = nums2[j-1]
else:
down = max(nums1[i-1],nums2[j-1])
return (up+down)/2.0
while l<r:
mid = (l+r)>>1
if mid==0:
if nums2[tar-1]>nums1[0]:
l = mid+1
else:
return solve(mid)
else:
j = tar-mid
if nums2[j-1]>nums1[mid]:
l = mid+1
elif nums1[mid-1]>nums2[j]:
r = mid-1
else:
return solve(mid)
return solve(l)