题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
解析:emmm 剑指offer分析了一大堆数据结构的时间复杂度。具体如下:
最后得出结论使用最大最小堆是最优雅的解法,我这里就练习了一下这种方法。要求中位数,我们可以定义一个最大堆,一个最小堆,始终维护两个堆,使最大堆中最大元素小于最小堆中最小元素。
首先要保证数据平均分配到两个堆,因此两个堆中元素数目之差不能超过1,我们可以在数据总数目是偶数时把数据插入最大堆,否则插入最小堆。
然后要保证最大堆中所有元素小于最小堆中所有元素。当总数据量为偶数时,我们应该将数据插入最大堆,此时判断要插入的数据与最小堆中最小元素大小情况,如果插入数据大于最小堆堆顶元素,那么把最小堆堆顶元素取出压入最大堆,将新数据插入最小堆,这就保证了最大堆堆顶元素永远小于最小堆堆顶元素。总数据量为奇数时同理。
这里注意python的heapq模块实现的是最小堆,可以将数据取反压入,模拟最大堆。
from heapq import *
class Solution:
def __init__(self):
self.min_s = []
self.max_s = []
def Insert(self, num):
# write code her
if not self.min_s and not self.max_s:
heappush(self.max_s, -num)
elif (len(self.min_s) + len(self.max_s)) & 1 == 0:
if num > self.min_s[0]:
tmp = heappop(self.min_s)
heappush(self.max_s, -tmp)
heappush(self.min_s, num)
else:
heappush(self.max_s, -num)
elif (len(self.min_s) + len(self.max_s)) & 1 != 0:
if num < -self.max_s[0]:
tmp = heappop(self.max_s)
heappush(self.min_s, -tmp)
heappush(self.max_s, -num)
else:
heappush(self.min_s, num)
def GetMedian(self, n = None):
# write code here
if (len(self.min_s) + len(self.max_s)) & 1 != 0:
return -self.max_s[0]
else:
return (-self.max_s[0] + self.min_s[0]) / 2.0
2019.3.23