我正在写一个程序比需要找到一组号码中的第N个最大的值算出一组号码在第N个最大值。这些数字是由程序生成的,但我没有足够的内存来存储N个数字。是否有比N更好的上限,可以存储?这组数字(和N)的大小的上限约为100,000,000。因为它们产生
注:数字是小数和列表可以包括重复。
[编辑]:我的内存限制为16 MB。
我正在写一个程序比需要找到一组号码中的第N个最大的值算出一组号码在第N个最大值。这些数字是由程序生成的,但我没有足够的内存来存储N个数字。是否有比N更好的上限,可以存储?这组数字(和N)的大小的上限约为100,000,000。因为它们产生
注:数字是小数和列表可以包括重复。
[编辑]:我的内存限制为16 MB。
这是一种多通道算法(因此,您必须能够多次生成相同的列表,或将列表存储到辅助存储中)。
第一遍:
通行证:
最后一关:
例如:如果你看到的范围是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.
另一种多通道的想法:
只需进行二分查找。选择范围的中点作为第一次猜测。你的通行证只需要做一个高于/低于计数来确定下一个估计值(可以通过计数来加权,或者为简化代码而简单地进行平均)。
如果我理解好,您的程序上限的内存使用情况是O(N)(可能N + 1)。您可以维护生成的值的列表,该列表比当前X(迄今为止的第N个最大值)大,按照最低的顺序排列。只要生成一个新的更大的值,就可以将当前的X替换为列表的第一个元素,并将刚刚生成的值插入列表中的相应位置。
这类似于另一个问题 - C Program to search n-th smallest element in array without sorting? - 在这里你可以得到一些答案。
该逻辑将同样适用于第N大/最小的搜索。
注意:我不是说这是重复的。
由于您有很多(接近10亿?)数字,这里是空间优化的另一种方法。
假设您的数字适合32位值,那么大约10亿将需要一段时间接近32GB的空间。现在,如果您可以承受大约128MB的工作内存,我们可以一次完成。
您能够再生同一组从开始的数字?如果是的话,可以在输出上多次传递:首先找到最大值,重新启动发生器,找到最小的数字,重新启动发生器,并重复此操作直到得到结果。
这将是一个真正的表现杀手,因为你有很多数字,并且需要很多通行证 - 但是在记忆方面,你只需要存储2个元素(当前最大值和一个“限制“,你在上一次传球中找到的号码)和一个传球计数器。
您可以通过使用优先级队列找到M个最大元素加快它(选择数μm,你能够装入内存),让您减少需要N/M的遍数。
如果您需要查找15个数字列表中的第10个最大元素,则可以通过其他方式节省时间。由于它是第10大元素,这意味着有15-10 = 5个元素比这个元素小 - 所以你可以找第6个最小的元素来代替。
我这样做了使用最小堆优先级队列,但我内存不足。 – snake 2009-07-05 16:38:21
然后你没有足够的内存来解决你的问题。我不认为你能比存储前N个号码做得更好。 – PanCrit 2009-07-05 16:49:53