所以,让我们说我有1亿Comparable
作为流媒体输入,我想输出那个输入的前100个(按顺序 - 这是微不足道的我想你,如果你可以找到前100名)。我假设某种插入排序最好,但实现这一目标的最佳方法是什么(如果它是最好的方式)?
约束条件是你肯定会一次看到一个对象(我肯定不能将整个集合放入内存中)。
我在考虑两种可能的解决方案:
1)一个简单的链表。因此,当前100个对象进入时,它们将被排序(花费O(n)时间 - 但是n = 100)。然后当每个连续的对象进入时,它将被正确插入(再次O(n),n = 100,时间),如果插入,它将踢出尾部(否则链接列表将保持不变,如果它'超过最大值)。
2)使用堆。我想我可以保留一个堆,插入堆中,然后丢弃根节点(堆顶部),如果堆的大小高于我的最大元素数(在我的情况下为100)。这应该意味着O(lg(n))运行时,对吧?由于元素的插入和根的删除都是O(lg(n)),对吧?
Java中的堆有没有好的库?我真的不想编写自己的堆结构。
P.S。
如果您想知道为什么我这样做,那就是幻想足球的目的。我有一个程序,可以在salaray帽的约束下找到一组玩家的最大投射点(它是一个强力算法)。事实上,完全是另一个问题,即如何解决背包问题,其中必须具有一定数量的不同类型的项目(即1 QB,3 WR,2 RB,1 TE,1 K和1防御。)
所以我有一大组(1,234)的球队给出了最低的预计积分数,但现在我试图找到拥有各种不同球员的球队。我认为一组三支球队是合理的解决(通过暴力):1,234选择3 = 312,419,184(根据我的计算,将花费大约一个半小时来处理)。我计算了一组球队'方差是玩家在每个团队中出现的次数(因此值越低,团队组别越大)。
答案 0 :(得分:2)
如果你要做的只是添加,你可以使用它。
public static <T> SortedSet<T> topValues(final int n, final Comparator<T> comparator) {
return new TreeSet<T>(comparator) {
@Override
public boolean add(T t) {
// if less than N in size, just try to add it.
if (super.size() < n)
return super.add(t);
T first = super.first();
// if smaller than the first, discard it.
if (comparator.compare(t, first) <= 0)
return false;
// otherwise try to add it.
super.remove(first);
super.add(t);
return true;
}
};
}
或者该类型已经是可比较的
public static <T extends Comparable<T>> SortedSet<T> topValues(final int n) {
return new TreeSet<T>() {
@Override
public boolean add(T t) {
// if less than N in size, just try to add it.
if (super.size() < n)
return super.add(t);
T first = super.first();
// if smaller than the first, discard it.
if (t.compareTo(first) <= 0)
return false;
// otherwise try to add it.
super.remove(first);
super.add(t);
return true;
}
};
}
只需将所有值添加到此集合中,它只会有n
个值,每次丢弃最小值。