给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
例:
输入:nums1 = [1,3], nums2 = [2] 输出:2.00000 解释:合并数组 = [1,2,3] ,中位数 2
# 1 暴力解法:合并,排序,直接查找,时间复杂度O((m+n)log (m+n))
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
for i in range(len(nums2)):
nums1.append(nums2[i])
nums1.sort()
num = len(nums1)
k = int(num/2)
if (num & 1) == 0:
return ((nums1[k]+nums1[(k-1)])/2)
else:
return (nums1[k])
# 2 合并两个有序数组,只用合并到中值即可。时间复杂度O((m+n))
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
m = len(nums1)
n = len(nums2)
lens = m + n
left, right = -1, -1 # 分割线左右两边的值
aStart, bStart = 0, 0 # 两个数组的开始下标
for i in range(lens//2 + 1): # 只用遍历到中值即可
left = right # 右边界赋值给左边界
if aStart < m and (bStart >= n or nums1[aStart] < nums2[bStart]): # 1数组还有值,并且1数组当前下标对应的值小于2数组当前下标对应的值或者2数组已经遍历完毕
right = nums1[aStart] # 则将1数组当前下标对应的值赋给右边界
aStart += 1 # 下标右移一位,判断下一个
else: # 与上个判断类似
right = nums2[bStart]
bStart += 1
if (lens & 1) == 0: # 按位与运算判断长度奇偶
return (left+right)/2.0 # 为偶数的情况
else:
return right
# 二分法,同样查询一半的值即可,每个数组判断一半,将较小的一半直接过滤,因为是有序数组,直接判断中值即可,不必一一比较,时间复杂度为O(log (m+n))
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
def getK(k): # k值,需要查询的第k大的值
id1, id2 = 0, 0 # 数组1的下标,数组2的下标
while True:
# 特殊情况
if id1 == m: # 数组1全部在中值左边
return nums2[id2 + k - 1] # 在数组2的当前下标下直接加上剩余需要判断的值
if id2 == n: # 数组2全部在中值左边
return nums1[id1 + k - 1] # 在数组1的当前下标下直接加上剩余需要判断的值
if k == 1: # k等于1时表明已经排除了小于中值的值,直接返回当前下标中较小的一方即可
return min(nums1[id1], nums2[id2])
# 正常情况
newid1 = min(id1 + k // 2 - 1, m - 1) # 数组1需要判断的位置下标
newid2 = min(id2 + k // 2 - 1, n - 1) # 数组2需要判断的位置下标
p1, p2 = nums1[newid1], nums2[newid2] # 判断下标对应的值
if p1 <= p2: # 若数组1的当前判断值较小,则说明判断下标以及之前的值全部都在中值左边,全部排除
k -= newid1 - id1 + 1 # 需要判断的k值减少排除的值
id1 = newid1 + 1 # 数组1从去除的下标后一位重新开始
else: # 同理
k -= newid2 - id2 + 1
id2 = newid2 + 1
m, n = len(nums1), len(nums2) # 数组1,数组2的长度
Length = m + n # 总长度
if Length % 2 == 1: # 若总数组长度为奇数
return getK((Length + 1) // 2) # 直接返回中值下标对应的值
else: # 若为偶数
return (getK(Length // 2) + getK(Length // 2 + 1)) / 2 # 返回中值左右两边的值相加取平均
三种方法,如果对时间复杂度没有要求的话,暴力还是最通俗易懂,暴力yyds |ू・ω・` )