python - 实现中值维护

标签 python algorithm heap

我正在尝试解决我正在学习的在线类(class)中的问题,但我相信我陷入了困境。

这就是问题

The goal of this problem is to implement the "Median Maintenance" algorithm. The text file contains a list of the integers from 1 to 10000 in unsorted order; you should treat this as a stream of numbers, arriving one by one. Letting xi denote the ith number of the file, the kth median mk is defined as the median of the numbers x1,…,xk. (So, if k is odd, then mk is ((k+1)/2)th smallest number among x1,…,xk; if k is even, then mk is the (k/2)th smallest number among x1,…,xk.)

Find the sum of the 1000 medians.

下面是我的代码,它输出了错误的答案,我似乎无法弄清楚出了什么问题

import heapq
# all_ints = list(map(int, open("stanford_algo/course_2_graph_search/median.txt").read().splitlines()))
all_ints = [6331, 2793, 1640, 9290, 225, 625, 6195, 2303, 5685, 1354]
min_heap_elements =  [all_ints[0]] # has all elements more than median
max_heap_elements =  [all_ints[1]] # has all elements less than median
heapq.heapify(min_heap_elements) # has all elements more than median
heapq._heapify_max(max_heap_elements) # has all elements less than median
medians = []
medians.append(all_ints[0])
medians.append(all_ints[1]) #doing this because I can see the first two elements are in decreasing order

for i, next_int in enumerate(all_ints[2:],start=3):
    if next_int > min(min_heap_elements):
        heapq.heappush(min_heap_elements, next_int)
        heapq.heapify(min_heap_elements)
    elif next_int <=  max(max_heap_elements):
        max_heap_elements.append(next_int)
        heapq._heapify_max(max_heap_elements)
    else:
        if len(min_heap_elements) > len(max_heap_elements):
            max_heap_elements.append(next_int)
            heapq._heapify_max(max_heap_elements)
        else:
            heapq.heappush(min_heap_elements, next_int)
            heapq.heapify(min_heap_elements)
    if len(max_heap_elements) - len(min_heap_elements) > 1:
        extract = max_heap_elements.pop(0)
        heapq.heappush(min_heap_elements, extract)
        heapq._heapify_max(max_heap_elements)
        heapq.heapify(min_heap_elements)
    elif len(min_heap_elements) - len(max_heap_elements) > 1:
        extract = min_heap_elements.pop(0)
        max_heap_elements.append(extract)
        heapq._heapify_max(max_heap_elements)
        heapq.heapify(min_heap_elements)
    median = [max(max_heap_elements), min(min_heap_elements)][(i)%2]
    medians.append(median)

sum(medians)%10000 # should be 9335

我在这里使用两个堆。一个用于将大于媒体的元素存储在最小堆 (min_heap_elements) 中,另一个堆 (max_heap_elements) 用于存储小于中位数的元素。对于每个新元素,如果它小于(或等于)最大堆的最大元素,我会将其添加到 max_heap_elements 中。我

如果新元素大于最小堆的最小元素,我会将其添加到 min_heap_elements 中。如果这两种情况都不是,我会查看哪个堆更短并将其添加到该堆中。

但是,我在这里正在做一些事情,但我无法具体说明。

编辑:

这些是我得到的中位数

>>> medians
[6331, 2793, 6331, 2793, 6331, 1640, 2793, 2303, 2793, 2303]

这就是我所期待的

>>> correct_medians
[6331, 2793, 2793, 2793, 2793, 1640, 2793, 2303, 2793, 2303]

最佳答案

问题在于如何计算两个堆的中位数,因为当索引为奇数时,不能保证左侧堆比右侧堆多一个元素。

相反,你应该这样做

if len(max_heap_elements) == len(min_heap_elements):
    median = max(max_heap_elements)
elif len(max_heap_elements) > len(min_heap_elements):
    median = max(max_heap_elements)
else:
    median = min(min_heap_elements)

另外,请注意,如果您使用堆,是因为您想要实现 O(nlogn) 解决方案,但是,通过重复调用 heapifymaxmin,您将无法获得所需的时间复杂度。

不要将 min(min_heap_elements) 写入 min_heap_elements[0],而是删除 heappush 之后的 heapify 调用,使用 heappop 而不是列表的 pop

最后,对于最大堆,您可以有一个包含负值的列表,因为 heapq 模块不支持最大堆,它们仅“支持”一些操作,例如 _heappop_max >,但没有 _heappush_max,因此您始终需要调用 _heapify_max

编辑: 如果时间复杂度不是要求,您可以使用标准库中的函数statistics.median_low

关于python - 实现中值维护,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58593657/

相关文章:

algorithm - 最大堆和插入

algorithm - 词入二叉堆

python - Python嵌套操作的幕后花絮

来自客户端的 Python Irc-Bot EOF 在套接字关闭和关闭时

python - 收集雨水的时间复杂度

python - 在 Python 中根据用户输入执行特定功能

Java : How to print heap stored as array,逐级

Python Quantlib : How to deal with RuntimeError 'addFixing(date, value)'

python - 如何创 build 置脚本以使 python 脚本在 Ubuntu 环境中可用?

python - 获取邻接列表中的所有叶子节点