【问题标题】:What is the best way to get a sorted list (of finite length) from a large set of input从大量输入中获取排序列表(有限长度)的最佳方法是什么
【发布时间】: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 是最省力的:一定要这样做!

标签: java algorithm sorting


【解决方案1】:

如果你所做的只是添加,你可以使用它。

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;
        }
    };
}

或者如果类型已经是 Comparable

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 值,每次都丢弃最小的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 2010-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-18
    相关资源
    最近更新 更多