当前位置: 首页 > 知识库问答 >
问题:

中位数维护的实施

夏炎彬
2023-03-14

我正在尝试解决一个在线课程中的问题,我相信我被卡住了。

这就是问题所在

该问题的目标是实现“中值维护”算法。文本文件包含按未排序顺序从1到10000的整数列表;您应该将其视为一个数字流,一个接一个地到达。让xi表示文件的第i个数字,第k个中值mk被定义为数字x1,…,xk的中值。(因此,如果k是奇数,那么mk是x1,…,xk中的第((k1)/2)个最小数;如果k是偶数,则mk是x1、…、xk中的第(k/2)个最小数。)

求1000个中位数的总和。

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

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),另一个用于存储小于中值的元素。对于每个新元素,如果其小于(或等于)最大堆中的最大元素,我将其添加到<code>max_heap_elements</code>中。我

如果新元素大于最小堆的最小元素,我将其添加到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]

共有2个答案

颜奇希
2023-03-14

我也经历了同样的过程,所以我的解决方案就在这里。

import heapq
import statistics

with open('home_work_week3_Median.txt', 'r') as file:
    line = file.read().strip().split('\n')
file.close()
assert len(line) == 10000

# solution with heapq
nn = []
num = 0

for n, v in enumerate(line):

    nn.append(v) 

#     index = (len(nn) - 1) // 2 # here we get the index of new list
#     new = heapq.nsmallest(n+1, nn) # get the smallest num of heapqed list
#     print(new[index], new, index)

    # here we combine it into one line
    num += int(heapq.nsmallest(n+1, nn)[(len(nn) - 1) // 2])

num%10000


# solution with statistics lib
num = 0

for index, number in enumerate(test):
    num += int(statistics.median_low(test[:index+1]))

num%10000

我不知道我的解决方案是否正确,两种解决方案的执行时间相同(约11秒)。我相信会更好

董意蕴
2023-03-14

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

相反你应该做

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)解决方案,但是,通过重复调用maxmin等函数,您将无法获得所需的时间复杂性。

取代< code > min(min _ heap _ elements) write < code > min _ heap _ elements[0],移除< code>heappush之后的< code>heapify调用,取代list的< code > pop use < code > heap pop 。

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

编辑:如果时间复杂度不是一个要求,您可以只使用标准库中的函数< code > statistics . median _ low 。

 类似资料:
  • 问题内容: 我有如下内容: 我对基本图片有2个问题: 1.如何获取标签? 通常,我是从dockerhub获得的,也就是说,我可以从dockerhub的openjdk存储库中获得。 如果我可以从任何本地docker命令获取所有标签,那么我不需要访问Web来获取标签,效率真的有点低吗? 2.基本图像安全吗? 我的意思是说我的基本形象是否一直存在? 查看上面的openjdk回购,这是一个官方回购。 我发

  • 我有一个类似于以下内容: 我有2个关于基本图像的问题: 通常,我从dockerhub获取它,比如说,我可以从dockerhub的openjdk存储库中获取它。 如果我可以从任何本地docker命令获取所有标签,那么我就不需要访问web来获取标签,真的有点低效率吗? 我是说如果我的基本形象一直在那里? 看看上面的openjdk repo,它是一个官方的repo。 我发现只有供我选择。但我认为在这个过

  • Navicat 为 MySQL、Oracle、PostgreSQL、SQLite、SQL Server 和 MariaDB 的数据库和数据库对象维护提供完整的解决方案。 要维护服务器对象,你可以在它上右击并在弹出菜单中 维护。 维 护 MySQL 或 MariaDB 维护表分析表 分析及保存表的键分布。在分析期间,MyISAM 及 BDB 表是以读入锁被锁定的。InnoDB 表是以写入锁被锁定的。

  • 节点数据同步 MongoDB 复制集中当从节点无法跟上主节点数据时,则该节点就需要节点数据同步,MongoDB 提供了两种数据同步的方式: 初始化节点数据同步 拷贝数据文件数据同步 初始化节点数据同步的优点是不需要集群停机,但会会一定程度上适度影响集群的正常读写,数据同步所花时间也稍微长于拷贝数据文件数据同步;而拷贝数据文件数据同步需要步骤较多,且需要停机窗口。本部分从三个方面说明节点数据同步,并

  • 如何维护唯一数组的? 例如,如果我有以下数组:

  • 开始之前,您可以查看添加到屏幕相关内容,快速掌握相关基础。 为了实现 PWA 应用添加至桌面的功能,我们需要准备 manifest.json 文件配置应用的图标、名称等信息。 项目中这些信息在哪里配置呢? 如何配置 项目的配置文件一般在 config 文件夹下,这里的配置也不例外,就在 config/manifest.js 中,开发中我们一般只需要关注该文件的配置内容即可满足开发需求。 confi