LeetCode findMedianSortedArrays Python3

给定两个有序数组 A 和 B,要求在 O(log(m+n)) 时间复杂度内找到中位数。示例:A = [1,3], B = [2],输出 2.0;A = [1,2], B = [3,4],输出 2.5。解决方案利用二分查找,找到分割点 i 和 j 使等长划分满足最值关系,确保 A[i-1] < B[j] 且 B[j-1] < A[i],最后处理边界情况,输出中位数。" 117333446,10997635,Spring框架中的依赖注入详解,"['Spring', '依赖注入', 'XML配置', 'Java']
摘要由CSDN通过智能技术生成

题目描述:给定两个大小为 m 和 n 的有序数组 A 和 B 。找出这两个有序数组的中位数,并且要求算法时间复杂度为 O(log(m+n))。可以假设这两个数组不会同时为空。
示例 1:
输入: A = [1,3], B = [2]
输出: 2.0
示例 2:
输入: A = [1,2], B = [3,4]
输出: (2+3) / 2 = 2.5

其实如果没有时间复杂度的要求,这个问题用 Python 实在是太简单了,感觉有点像作弊:

def findMedianSortedArrays(A, B):
	res = []
	res.expand(A)
	res.expand(B)
	res = sorted(res)
	if len(res) % 2 == 0:
		half = len(res) // 2
		return (res[half-1] + res[half]) / 2.0
	else:
		return res[len(res)//2] / 1.0

但是这个代码在效率上是不合格的,因为只是使用 sorted 函数 O 就已经爆掉了。看到给出的示例大概是这样的:

def findMedianSortedArrays(A, B):
	m, n = len(A), len(B)
	if m > n:
		A, B, m, n = B, A, n, m
	if n < 1:
		raise ValueError
	
	imin, imax, half = 0, m, (m+n+1) // 2
	while imin <= imax:
		i = (imin+imax) // 2
		j = half - i
		if i < m and A[i] < B[j-1]:
			imin = i + 1
		elif j > 0  and B[j] < A[i-1]:
			imax = i - 1
		else:
			if i == 0: max_left = B[j-1]
			elif j == 0: max_left = A[i-1]
			else: max_left = max(A[i-1], B[j-1])

			if (m+n) % 2 != 0:
				return max_left / 1.0
			else:
				if i == m: min_right = B[j]
				elif j == n: min_right = A[i]
				else: min_right = min(A[i], B[j])
				return (max_left+min_right) / 2.0

官方给出的示例解释非常专业,所以我看了很久才看懂。这里简单解释一下这个算法的思想:

  • 所谓中位数的含义就是将一个集合划分成两个等长的子集,使得其中一个子集中的最大值小于另一个子集中的最小值,这样就得到了中位数的两个判据:等长划分、最值关系
  1. 首先找到两个分割点 i 和 j 分别分割 A 和 B, 保证分割后的 l e n ( A l e f t ) + l e n ( B l e f t ) len(A_{left}) + len(B_{left}) len(Aleft)+len(Bleft) l e n ( A r i g h t ) + l e n ( B r i g h t ) len(A_{right}) + len(B_{right}) len(Aright)+len(Bright)相等,这点由代码的10、11行保证,即保证了等长划分。
  2. 之后要保证两部分最值间的关系,因为原始的 A 和 B 都是有序的,所以只需沿着划分点比较就可以了,这省了很多事。最后确定的划分点应该满足
    A [ i − 1 ] &lt; B [ j ] , B [ j − 1 ] &lt; A [ i ] A[i-1]&lt;B[j],B[j-1]&lt;A[i] A[i1]<B[j]B[j1]<A[i]
    发现不满足,就根据不满足的情况调整 i 的搜索区间,就是代码中的二分查找。
  3. 最后解决边界问题,即 i = 0, m,j = 0, n 的情况,分类讨论一下即可。最后就找到了左部分的最大值和右部分的最小值,输出平均数作为返回值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值