我正在编写一个程序而不是需要在一组数字中找到第N个最大值。这些数字是由程序生成的,但我没有足够的内存来存储N个数字。有没有比N更好的上限可以实现存储?数字组(和N)大小的上限约为100,000,000。
注意:数字是小数,列表可以包含重复数。
[编辑]:我的内存限制是16 MB。
答案 0 :(得分:3)
你能从头开始重新生成同一组数字吗?如果是,您可以对输出进行多次传递:首先查找最大值,重新启动生成器,找到小于该值的最大数字,重新启动生成器,然后重复此操作直到获得结果。
这将是一个真正的性能杀手,因为你有很多数字并且需要很多传球 - 但是在内存方面,你只需要存储2个元素(当前最大值和“限制”) ,你在上一次传球中找到的号码)和传球计数器。
你可以通过使用你的优先级队列来找到M个最大的元素(选择一些你能够适应内存的M)来加快速度,让你减少N / M所需的传球次数。
如果您需要查找15个数字列表中的第10大元素,您可以通过相反的方式来节省时间。由于它是第10大元素,这意味着有15-10 = 5个元素小于这个元素 - 所以你可以寻找第6个最小的元素。
答案 1 :(得分:3)
这是一种多遍算法(因此,您必须能够多次生成相同的列表,或将列表存储到二级存储中)。
第一遍:
在第一次之后传递:
最后一遍:
示例:如果您看到的范围是0.0到1000.0,那么您的容器范围将为:
(- 0.0 - 100.0]
(100.0 - 200.0]
(200.0 - 300.0]
...
(900.0 - 1000.0)
如果您通过计数找到您的号码在(100.0 - 2000.0)箱中,您的下一组箱将是:
(100.0 - 110.0]
(110.0 - 120.0]
etc.
另一个多遍想法:
只需进行二分查找。选择范围的中点作为第一个猜测。您的传递只需要执行高于/低于计数以确定下一个估计(可以通过计数加权,或者简单的平均值来简化代码)。
答案 2 :(得分:1)
这类似于另一个问题 - C Program to search n-th smallest element in array without sorting? - 你可以在那里得到一些答案 该逻辑同样适用于第N个最大/最小搜索 注意:我并不是说这与此重复。
由于您有很多(近10亿?)数字,这是空间优化的另一种方式 让我们假设您的数字符合32位值,因此大约10亿将需要接近32GB的空间。现在,如果你能负担大约128MB的工作记忆,我们可以一次性完成。
答案 3 :(得分:0)
如果我理解的话,程序的上限内存使用量是O(N)(可能是N + 1)。您可以维护一个生成值列表,该列表大于当前X(目前为第N个最大值)排序的最低值。只要生成了一个新的更大的值,就可以用列表的第一个元素替换当前的X,并将刚刚生成的值插入到列表中的相应位置。
答案 4 :(得分:0)
sort -n | uniq -c和Nth应该是第N行