我正在关注以下博客并了解如何以非常微妙的方式获得中位数。博客是here
现在,我将以下函数添加到streamMedian类中以获取插入的数字的平均值而不是获得所需的输出
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)。提前致谢。
答案 0 :(得分:2)
您正在将负数推送到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()
函数的变量。
答案 1 :(得分:1)
AChampion的回答正确识别您当前代码的问题,并在仍然使用您当前的算法时提供合理的解决方案。但是,该算法效率不高(需要O(N)
次)并且您可以做得更好。
具体来说,除了将其推入其中一个堆之外,您应该将您要插入的值添加到累积总和中。这样,当你需要得到一个均值时,你可以在恒定时间内计算它(只需一个分区):
class streamMedian:
def __init__(self):
self.minHeap, self.maxHeap = [], []
self.cumulative_sum = 0.0 # new instance variable
self.N=0
def insert(self, num):
self.cumulative_sum += num # add each value to it
# rest of insert code...
# median code...
def getMean(self):
return self.cumulative_sum / self.N # compute the mean in constant time
请注意,如果您正在使用Python 2(它看起来像你),那么使用浮点值cumulative_sum
而不是整数{{来初始化0.0
非常重要。 1}}(否则会很自然)。当你在Python 2中划分两个整数时,你将得到另一个整数,向下舍入。如果你计算0
和1
(你期待2
的平均值,那么这可能是不可取的,但你得到{{} {1}}如果你只做1.5
)。 Python 3做得更好(你总是从常规部门得到一个浮点数,并且可以使用1
运算符明确请求" floor" division)。如果您想在Python 2中获得相同的语义,可以将(1 + 2) / 2
放在模块的顶部。