当前位置: 首页 > 后端技术 > Python

【最简单的实现】计算数据流中的中位数Leetcode算法Python实现

时间:2023-03-26 16:04:51 Python

1.问题描述:中位数是有序列表中间的数。如果列表长度是偶数,则中位数是中间两个数字的平均值。例如[2,3,4]的中位数是3[2,3]的中位数是(2+3)/2=2.5设计一个支持以下两种操作的数据结构:voidaddNum(intnum)-将数据流中的整数添加到数据结构中。doublefindMedian()-返回到目前为止所有元素的中值。例子:addNum(1)addNum(2)findMedian()->1.5addNum(3)findMedian()->2二、问题分析1、如果有数据流:[3,1,9,25,12,…]每流入一条数据,先追加到链表尾部,然后排序,然后计算中位数,过程如下:3->[3]中位数:31->[3,1]->[1,3]中位数:(1+3)/2=2.09->[1,3,9]->[1,3,9]中位数:325->[1,3,9,25]->[1,3,9,25]中位数:(3+9)/2=6.012->[1,3,9,25,12]->[1,3,9,12,25]中位数:9最后输出的中位数列表为:[3,2.0,3,6.0,9,...]2.计算过程总结:先排序,再减半如图:可见,求中位数两种情况:列表长度为奇数时:直接取中间数列表长度为偶数时:计算中间两个数的平均值取中值即可。defrunning_medians_naive(iterable):medians=[]values=[]fori,xinenumerate(iterable):values.append(x)values.sort()ifi%2==0:medians.append(values[i//2])else:medians.append((values[i//2]+values[i//2+1])/2)returnmediansrunning_medians_naive([3,1,9,25,12])观察上面算法实现的时间复杂度,可以发现每次都要对list进行排序,比较耗时。4.堆的实现Heap仔细观察计算过程,可以发现取中位数只和链表中心的1-2个值有关,如图:和思路很像heap的Heap,可以把median的左半部分折叠看做是大顶堆max-heap,右半部分看做是小顶堆min-heap,这样堆就可以用了来降低时间复杂度。Python实现由两部分组成:max-heap堆和中值算法。4.1、Max-heap堆类Heap:def__init__(self,key=lambdax:x):self.data=[]self.key=key@staticmethoddef_parent(idx):return(idx-1)//2@staticmethoddef_left(idx):返回idx*2+1@staticmethoddef_right(idx):返回idx*2+2defheapify(self,idx=0):whileidxself.key(self.data[mid_idx]):mid_idx=leftifrightself.key(self.data[mid_idx]):mid_idx=rightifmid_idx!=idx:self.data[mid_idx],self.data[idx]=self.data[idx],self.data[mid_idx]idx=mid_idxelse:breakdefadd(self,x):self.data.append(x)idx=len(self.data)-1whileidx>0:p=Heap._parent(idx)ifself.key(self.data[idx])>self.key(self.data[p]):self.data[idx],self.data[p]=self.data[p],self.data[idx]idx=pelse:breakdefpeek(self):returnself.data[0]defpop(self):ret=self.data[0]self.data[0]=self.data[len(self.data)-1]delself.data[len(self.data)-1]self.heapify()returnretdef__bool__(self):returnlen(self.data)>0def__len__(self):returnlen(self.data)def__repr__(self):returnrepr(self.data)4.2、取中位数defrunning_medians_heap(iterator):medians=[]max_heap=Heap(lambdax:x)min_heap=Heap(lambdax:-x)fori,xinenumerate(iterator):ifi%2==0:max_heap.add(x)min_heap.add(max_heap.pop())medians.append(min_heap.peek())else:min_heap.add(x)max_heap.add(min_heap.pop())medians.append((max_heap.peek()+min_heap.peek())/2)returnmediansrunning_medians_heap([3,1,9,25,12])具体算法原理可参考视频:https://www.bilibili.com/video...转载请注明出处。如果您有任何意见或建议,请联系公众号或邮件:bjstorm#foxmail.com