【发布时间】:2014-10-09 05:03:39
【问题描述】:
假设我有 1 亿个 Comparable 作为流输入,我想输出该输入的前 100 个(按顺序 - 如果你能找到前 100 个,我认为这是微不足道的)。我假设某种插入排序是最好的,但是实现这一点的最佳方法是什么(如果它甚至是最好的方法)?
限制条件是你肯定会看到每个对象,一次一个(我肯定不能将整个集合放入内存中)。
我在考虑两种可能的解决方案:
1) 一个简单的链表。因此,当前 100 个对象进入时,它们将被排序(需要 O(n) 时间——但 n = 100)。然后随着每个连续的对象进来,它会被正确插入(再次O(n),n = 100,时间),如果插入,它将踢出尾巴(否则如果超过最大值,则链表将保持不变值)。
2) 使用堆。我想我可以保留一个堆,插入到堆中,然后如果堆的大小超过我的最大元素数(在我的情况下为 100),则丢弃根节点(堆的顶部)。这应该意味着 O(lg(n)) 运行时,对吧?因为插入元素和删除根都是O(lg(n)),对吧?
在 Java 中有什么好的堆库吗?我真的不想编写自己的堆结构。
附言
如果您想知道我为什么要这样做,那是为了梦幻足球。我有一个程序可以在工资帽的约束下找到一组玩家的最大投影点(这是一种蛮力算法)。事实上,这完全是另一个问题,即如何解决背包问题,您必须拥有一定数量的不同类型的物品(即 1 QB、3 WR、2 RB、1 TE、1 K和 1 次防御)。
所以我有一大组 (1,234) 支球队,它们给出了最低的预计分数,但现在我试图找到拥有各种不同球员的球队组。我认为由三个团队组成的小组是合理的(通过蛮力):1,234 选择 3 = 312,419,184(根据我的计算,处理大约需要一个半小时)。我将一组球队的方差计算为一个球员在每支球队中出现的次数(因此值越低,该组球队的方差越高)。
【问题讨论】:
-
使用
TreeSet只存储前 100 个? -
@DavidWallace 谢谢,我认为这正是我正在寻找的(就堆实现而言)。我只需要正确地对项目进行排序(这意味着适当地实现
compareTo方法)。 -
如果你的 100 是一个常数(看起来像这样),用大 O 术语来说,不管你做什么,你的算法总是
O(n)和n的大小输入。我不认为堆和数组(使用插入排序)之间的性能差异对于仅 100 个元素来说会那么大。您可以简单地同时尝试并测量。 -
@VincentvanderWeele 既然我问了这个问题,我应该给它们计时并回复你——尽管你可能是对的......唯一的问题是插入排序需要更多的工作(在我的部分)而不是使用
TreeSet类。 -
如果使用
TreeSet是最省力的:一定要这样做!