这是刷到的leetcode的第四道题,虽然说每天一道题好像也不多,但是写完之后还有一些比对工作,看看别的算法的优缺点之类的,这才刚写了没几道题竟然还有些坚持不下去了,不行啊,得赶紧振作起来~坚持坚持~
题目描述:
给定两个大小为 m 和 n 的有序数组
nums1
和nums2
。请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设
nums1
和nums2
不会同时为空。示例 1:
nums1 = [1, 3] nums2 = [2] 则中位数是 2.0示例 2:
nums1 = [1, 2] nums2 = [3, 4] 则中位数是 (2 + 3)/2 = 2.5
看到这个首先想到的就是把两个数组合起来,放在一起,然后排序求中位数:(156ms)
def getMiddle(a,b): a.extend(b) c = sorted(a) print(c) lenc=len(c) if lenc%2==1: return c[lenc//2] else: return (c[lenc//2-1]+c[lenc//2])/2
这个思路感觉没什么好解释的,常规思路,但是用到了排序,复杂度是O((m+n)log(m+n)),不符合题目要求的复杂度,自己意识也没有想到好的办法。下面是官方题解:
观法题解的思路是将两个数组都进行切分,第一个在i的位置进行切分,两一个在j的位置进行切分,这样把两个数组都转换成了两部分,leftA+rightA,leftB+rightB,可以将整体切出两个部分来,如下图所示:
我们所要做的其实就是:
1.len(left_part)==len(right_part) (均分成两部分)
2.max_left <= right_min (获取中位数)
3.根据m+n长度的奇偶性来进行最终中位数的判断
官方题解答案:(148ms)
class Solution: def findMedianSortedArrays(self,a,b): m,n=len(a),len(b) if m>n: a,b,m,n=b,a,n,m #短数组在前 if n==0: return ValueError imin,imax,half_len=0,m,int((m+n+1)/2) while imin <=imax: i=(imin+imax)//2 j=half_len-i #print(j) #print(i) if i<m and a[i]<b[j-1]: imin = i+ 1 elif i>0 and a[i-1]>b[j]: imax=i-1 else: #极端条件假设 if i==0:left_max=b[j-1] elif j==0:left_max=a[i-1] else: left_max = max(a[i-1],b[j-1]) if (m+n)%2==1: return left_max if i==m:right_min =b[j] elif j==n:right_min=a[i] else: right_min=min(a[i],b[j]) if (m+n)%2==0: return (left_max+right_min)/2
复杂度分析
时间复杂度:O(log(min(m,n))),
首先,查找的区间是 [0, m][0,m]。 而该区间的长度在每次循环之后都会减少为原来的一半。 所以,我们只需要执行 log(m) 次循环。由于我们在每次循环中进行常量次数的操作,所以时间复杂度为 O(log(m))。 由于 m≤n,所以时间复杂度是 O(log(min(m,n)))。空间复杂度:O(1), 我们只需要恒定的内存来存储 9 个局部变量, 所以空间复杂度为 O(1)。