Python 理解使用堆从整数流中获取平均值
我关注下面的博客,了解如何以一种非常微妙的方式获得中间值。这个博客是 现在,我将下面的函数添加到streamMedian类中,以获得插入的数字的平均值,而不是所需的输出Python 理解使用堆从整数流中获取平均值,python,algorithm,heap,Python,Algorithm,Heap,我关注下面的博客,了解如何以一种非常微妙的方式获得中间值。这个博客是 现在,我将下面的函数添加到streamMedian类中,以获得插入的数字的平均值,而不是所需的输出 import heapq class streamMedian: def __init__(self): self.minHeap, self.maxHeap = [], [] self.N=0 def insert(self, num): if self.N
import heapq
class streamMedian:
def __init__(self):
self.minHeap, self.maxHeap = [], []
self.N=0
def insert(self, num):
if self.N%2==0:
heapq.heappush(self.maxHeap, -1*num)
self.N+=1
if len(self.minHeap)==0:
return
if -1*self.maxHeap[0]>self.minHeap[0]:
toMin=-1*heapq.heappop(self.maxHeap)
toMax=heapq.heappop(self.minHeap)
heapq.heappush(self.maxHeap, -1*toMax)
heapq.heappush(self.minHeap, toMin)
else:
toMin=-1*heapq.heappushpop(self.maxHeap, -1*num)
heapq.heappush(self.minHeap, toMin)
self.N+=1
def getMedian(self):
if self.N%2==0:
return (-1*self.maxHeap[0]+self.minHeap[0])/2.0
else:
return -1*self.maxHeap[0]
def getMean(self):
sum = 0
for num in self.maxHeap:
sum += num
for num in self.minHeap:
sum += num
return sum/self.N
这是对streamMedian类的函数调用
test = streamMedian()
test.insert(1)
test.insert(2)
test.insert(3)
print test.getMedian()
print test.getMean()
这里的中位数应该是2,平均值应该是2(而不是0是输出)。提前谢谢 您正在将负数推送到您的
maxHeap
(-1*num
)。
您需要在getMean()
中反转该选项,例如:
def getMean(self):
total = 0
for num in self.maxHeap:
total -= num
for num in self.minHeap:
total += num
return total/self.N
或者:
def getMean(self):
return (abs(sum(self.maxHeap)) + sum(self.minHeap))/self.N
注意:不要使用
sum
作为变量,因为它隐藏了python内置的sum()
函数 您正在将负数推送到您的maxHeap
(-1*num
)。
您需要在getMean()
中反转该选项,例如:
def getMean(self):
total = 0
for num in self.maxHeap:
total -= num
for num in self.minHeap:
total += num
return total/self.N
或者:
def getMean(self):
return (abs(sum(self.maxHeap)) + sum(self.minHeap))/self.N
注意:不要使用
sum
作为变量,因为它隐藏了python内置的sum()
函数 AChampion的回答正确地识别了当前代码的问题,并在仍然使用当前算法的情况下提供了合理的修复。但是,该算法不是很有效(需要O(N)
时间),您可以做得更好
具体地说,除了将插入的值推送到某个堆上之外,还应该将插入的值添加到累积总和中。这样,当您需要获得平均值时,您可以在恒定时间内计算它(只需一次除法):
请注意,如果您使用的是Python 2(看起来您是这样的),则使用浮点值
0.0
而不是整数0
初始化cumulative_sum
非常重要。在Python2中,当您除以两个整数时,您将得到另一个整数,向下舍入。如果您正在计算1
和2
的平均值(您期望1.5
,但如果您只进行(1+2)/2
,您将得到1
)。Python3做得更好(您总是从常规除法中得到一个浮点,并且可以使用/
操作符显式请求“floor”除法)。如果您想在Python 2中获得相同的语义,可以将来自“未来”导入分部的放在模块顶部。AChampion的回答正确地识别了当前代码的问题,并在仍然使用当前算法的情况下提供了合理的修复。但是,该算法不是很有效(需要O(N)
时间),您可以做得更好
具体地说,除了将插入的值推送到某个堆上之外,还应该将插入的值添加到累积总和中。这样,当您需要获得平均值时,您可以在恒定时间内计算它(只需一次除法):
请注意,如果您使用的是Python 2(看起来您是这样的),则使用浮点值0.0
而不是整数0
初始化cumulative_sum
非常重要。在Python2中,当您除以两个整数时,您将得到另一个整数,向下舍入。如果您正在计算1
和2
的平均值(您期望1.5
,但如果您只进行(1+2)/2
,您将得到1
)。Python3做得更好(您总是从常规除法中得到一个浮点,并且可以使用/
操作符显式请求“floor”除法)。如果您想在Python 2中获得相同的语义,可以将来自未来导入部门的放在模块顶部。应编辑(1+2+3)/3==2
。谢谢平均值应(1+2+3)/3==2
编辑。谢谢你,这不是仍然是O(n)
只是分散在每个插入上吗?就像你仍然在为每个O(n)
项目执行+=
操作一样。不同之处在于每次调用getMean()
,只调用O(n)
一次(或者使用流式计算没有意义)。如果你调用getMean
O(n)
次,那么每次调用的值加起来的成本会分摊到O(1)
。这不是仍然O(n)
只是分散在每个插入上吗?就像你仍然在为O(n)
的每个项目执行+=
操作一样。不同之处在于每次调用getMean()
,只调用O(n)
一次(或者使用流式计算没有意义)。如果调用getMean
O(n)
次,则每次调用的值相加成本将摊销到O(1)
。