如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值
链接
方法一
- 使用大堆存储左边的值
- 使用小堆存储右边的值
- 0 <= 保证大堆数据的长度 - 小堆数据的长度 <=1
- 数据长度为奇数时, 中位数为大堆堆顶
- 在python中只能使用小堆 使用最大堆时存储 -num
- 每个添加数据时,先要判断往哪个堆插入 然后balance
import heapq
class MedianFinder:
def __init__(self):
"""
initialize your data structure here.
"""
self.min_heap = []
self.max_heap = []
def addNum(self, num: int) -> None:
if self.max_heap and num >= -self.max_heap[0]:
# 如果大堆不为空且 num大于大碓顶 应该小堆插入
heapq.heappush(self.min_heap, num)
else:
heapq.heappush(self.max_heap, -num)
self.balance()
def balance(self):
if len(self.min_heap) > len(self.max_heap):
min_heap_top = heapq.heappop(self.min_heap)
heapq.heappush(self.max_heap, -min_heap_top)
elif len(self.max_heap) - len(self.min_heap) > 1:
max_heap_top = - heapq.heappop(self.max_heap)
heapq.heappush(self.min_heap, max_heap_top)
def findMedian(self) -> float:
if len(self.min_heap) != len(self.max_heap):
return -self.max_heap[0]
else:
return (-self.max_heap[0] + self.min_heap[0]) /2
方法二
思路同方法1, 效率略优于方法1
区别如下:
插入数据时 使用 heapq.heappushpop 不需要显示的balance最大堆和最小堆
最后 最小堆的长度较大 所以为奇数时 输出 最小堆堆顶
class MedianFinder1:
def __init__(self):
"""
initialize your data structure here.
"""
# 初始化大顶堆和小顶堆
self.max_heap = []
self.min_heap = []
def addNum(self, num: int) -> None:
if len(self.max_heap) == len(self.min_heap):
# 先加到大顶堆,再把大堆顶元素加到小顶堆
heapq.heappush(self.min_heap, -heapq.heappushpop(self.max_heap, -num))
else: # 先加到小顶堆,再把小堆顶元素加到大顶堆
heapq.heappush(self.max_heap, -heapq.heappushpop(self.min_heap, num))
def findMedian(self) -> float:
if len(self.min_heap) == len(self.max_heap):
return (-self.max_heap[0] + self.min_heap[0]) / 2
else:
return self.min_heap[0]