获取集合中N个最小的[可比较]项目

时间:2011-03-29 04:51:00

标签: java sorting collections

我有一个未分类的对象集合[可比较],是否有可能获得列表集合的子列表而无需调用sort?

我正在考虑使用有限容量执行SortedList的可能性,但这看起来不是正确的选项。

我可以很容易地写出这个,但我想知道是否还有另一种方法。

我无法修改现有集合的结构。

4 个答案:

答案 0 :(得分:5)

由于您不想调用sort(),因此您似乎正在尝试避免 O(n log(n))运行时成本。 实际上是在 O(n)时间内完成此操作的方法 - 您可以使用selection algorithm

在Guava库中有一些方法可以做到这一点(谷歌的核心Java库);查看Ordering并查看:

这些是quickselect的实现,因为它们是一般编写的,您可以在Set上调用它们并获取k最小的事物列表。如果您不想使用整个Guava库,那么文档链接到源代码,我认为将方法移植到项目中应该很简单。

如果你不想偏离标准库太远,你总是可以使用像TreeSet这样的有序集合,虽然这可以获得对数插入/删除时间而不是漂亮的 O( 1)基于散列的Set的性能,最终最终成为 O(n log(n))。其他人提到使用堆。这也将为您提供 O(n log(n))运行时间,除非您使用某些fancier heap variants。如果你正在寻找其中一个,那就有一个fibonacci heap implementation in GraphMaker

其中哪些有意义取决于您的项目,但我认为这涵盖了大部分选项。

答案 1 :(得分:1)

我可能会创建一个有序集。将未分类集合中的前N个项目插入到已排序集合中。那么对于未分类的集合的剩余部分:

  1. 在排序集中插入每个项目
  2. 从已排序的集合中删除最大的项目
  3. 重复,直到您处理了未排序集合中的所有项目

答案 2 :(得分:1)

是的,如果项目小于最大堆中的最大值(通过检查get()“,则可以将它们全部放入固定大小为N的max heap data structure中偷看“方法”。一旦你这样做了,根据定义,它们将是最小的N.最佳实现将使用O(M)+lg(N)O(M)(其中M是集合的大小)性能执行,这在理论上是最快的。这是一些伪代码:

MaxHeap maxHeap = new MaxHeap(N);
for (Item x : mySetOfItems) {
  if (x < maxHeap.get()) {
    maxHeap.add(x);
  }
}

Apache Commons Collections class PriorityBuffer似乎是他们的旗舰二进制堆数据结构,尝试使用那个。

答案 3 :(得分:0)