给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
时间复杂度为O(log(m+n)),基本是二分查找,如果不考虑时间复杂度的情况下,可以用归并排序,先合并成有序数组,然后计算中位数轻而易举。怎么理解二分查找?
首先选择数组中间的数字和需要查找的目标值比较
如果相等最好,就可以直接返回答案了
如果不相等
如果中间的数字大于目标值,则中间数字向右的所有数字都大于目标值,全部排除
如果中间的数字小于目标值,则中间数字向左的所有数字都小于目标值,全部排除
注意的点是:
while循环中 left 和 right 的关系,到底是 left <= right 还是 left < right
迭代过程中 middle 和 right 的关系,到底是 right = middle - 1 还是 right = middle
1.当 A 数组和 B 数组的总长度是偶数时
2.当总长度是奇数
为了保证 max ( A [ i - 1 ] , B [ j - 1 ])) <= min ( A [ i ] , B [ j ])),因为 A 数组和 B 数组是有序的,所以 A [ i - 1 ] <= A [ i ],B [ i - 1 ] <= B [ i ] 这是天然的,所以我们只需要保证 B [ j - 1 ] < = A [ i ] 和 A [ i - 1 ] <= B [ j ] 所以我们分两种情况讨论:
B [ j - 1 ] > A [ i ]
我们需要增加 i ,为了数量的平衡还要减少 j ,幸运的是 j = ( m + n + 1) / 2 - i,i 增大,j 自然会减少。
A [ i - 1 ] > B [ j ]
我们要减少 i ,增大 j 。
上边两种情况,我们把边界都排除了,需要单独讨论。
当 i = 0, 或者 j = 0,也就是切在了最前边。
当 j = 0 时,最大的值就是 A [ i - 1 ] ;当 i = 0 时 最大的值就是 B [ j - 1] 。右半部分最小值和之前一样。
当 i = m 或者 j = n,也就是切在了最后边。
此时左半部分最大值和之前一样。右半部分当 j = n 时,最小值就是 A [ i ] ;当 i = m 时,最小值就是B [ j ] 。
上边的第一个条件我们其实可以合并为 j=(m+n+1)/2−ij = ( m + n + 1) / 2 - ij=(m+n+1)/2−i,因为如果 m+nm + nm+n 是偶数,由于我们取的是 intintint 值,所以加 111 也不会影响结果
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
m, n = len(nums1), len(nums2)
if m > n:
nums1, nums2, m, n = nums2, nums1, n, m
imin, imax, half_len = 0, m, (m + n + 1) // 2
while imin <= imax:
i = (imin + imax) // 2
j = half_len - i
if i < m and nums2[j-1] > nums1[i]:
imin = i + 1
elif i > 0 and nums1[i-1] > nums2[j]:
imax = i - 1
else:
if i == 0:
max_of_left = nums2[j-1]
elif j == 0:
max_of_left = nums1[i-1]
else:
max_of_left = max(nums1[i-1], nums2[j-1])
if (m + n) % 2 == 1:
return max_of_left
if i == m:
min_of_right = nums2[j]
elif j == n:
min_of_right = nums1[i]
else:
min_of_right = min(nums1[i], nums2[j])
return (max_of_left + min_of_right) / 2.0