提取一定数最高值,在一个列表
题
我寻求显示固定的项目数量在网页上根据它们各自的权重(由一个 Integer
).本列表,这些项目是发现可以的几乎任何大小。
第一个解决方案就是要做一个 Collections.sort()
并得到该项目一一个通过 List
.是否有一个更优雅的方案,虽然这可能被用来准备,也就是说,顶八个项目?
解决方案
只是去Collections.sort(..)
。它是足够有效的。
此算法提供保证的n log(n)的性能。
您的可以的尝试实施一些更有效的您的具体情况的,如果你知道你的列表中的一些独特的性能,但是这是没有理由的。此外,如果您的列表来自一个数据库,例如,你可以有LIMIT
它与订购它,而不是在代码中。
其他提示
你的选择:
做一个
线性搜索,保持前N重沿途发现。这应该快于排序lengthly名单,如果由于某种原因,你不能再使用的排序之间的结果显示网页(例如该清单是在迅速改变).更新:我站在正在直线索一定是更好的比排序。看到了维基百科的文章"Selection_algorithm选择k最小的或大的元素"为更好选择的算法。
手动保持
List
(原的一个或一个平行的一)按重量的顺序。你可以使用的方法一样 集合。binarySearch() 确定其中插入每一个新的项目。维持
List
(原的一个或一个平行的一)按重量以通过调用 集合。sort() 之后每次修改,批修改,或者只是前所显示(可能维持一个修改标志,以避免排序已排列表)。手动维持一个第二(可能是重订的)的数据结构的前N项目。这个数据结构是随时更新的原始数据结构的修改。你可以创建自己的数据结构包裹的原始名单和这个"顶级N高速缓冲存储器"在一起。
您可以使用最大堆。
如果从数据库中的数据起源,穿上该列的索引,使用ORDER BY和TOP或LIMIT获取只需要显示的记录。
或者一个优先级队列。
使用美元:
List<Integer> topTen = $(list).sort().slice(10).toList();
不使用美元,应使用sort()
Collections.sort()
它,然后使用list.sublist(0, n)
获得前n项。
由于你说项从中提取这些前N可以是任何尺寸的,等等的列表可以是大I假设,我会增加上述简单sort()
答案(其完全适当的合理大小的输入)通过建议的大部分工作这里是找到顶N - 然后分选那些N是微不足道的。是:
Queue<Integer> topN = new PriorityQueue<Integer>(n);
for (Integer item : input) {
if (topN.size() < n) {
topN.add(item);
} else if (item > topN.peek()) {
topN.add(item);
topN.poll();
}
}
List<Integer> result = new ArrayList<Integer>(n);
result.addAll(topN);
Collections.sort(result, Collections.reverseOrder());
这里的堆(一个最小堆)至少在尺寸上的限制。有没有真正的需要,使堆了所有项目的。
没有,真的没有。至少不是使用Java的内置方法。
有巧妙的方法来从列表比O(n*log(n))
操作更快得到物品的最高(或最低)N号,而是需要你手工编写代码这一解决方案。如果物品撑条相对低(不超过几百),采用Collections.sort()
排序,然后抓住前N个数字的数目是去IMO的方式。
取决于有多少。让Ñ定义为键的总数,并且m为要显示的数目。结果
排序整个事情:O(nlogn)
结果
在未来数最高每次扫描数组:O(n*m)
结果
所以,问题是 - 什么是到m信息n之间的关系?
如果m < log n
,扫描效率会更高。结果
否则,m >= log n
,这意味着排序会更好。 (因为对于m = log n
的边缘情况下,它实际上并没有问题,但排序也会给你的,效益好,排数组,这总是好的。
如果该列表的大小是N,并且要检索的项数是K,需要调用Heapify列表中,其将列表(其必须是可转位的,例如数组)上成优先队列。 (参见在 http://en.wikipedia.org/wiki/Heapsort heapify功能)
在堆上(最大项)的顶部检索的项目需要O(LG N)的时间。所以,你的总时间将是:
O(N + K LG N)
这比O(N LG N)假设ķ更好是小于N小得多。
如果保持有序阵列,或者使用不同的数据结构是不是一种选择,你可以尝试像下面这样。所述O时间类似于排序大阵但在实践中,这应该是更有效的。
small_array = big_array.slice( number_of_items_to_find );
small_array.sort();
least_found_value = small_array.get(0).value;
for ( item in big_array ) { // needs to skip first few items
if ( item.value > least_found_value ) {
small_array.remove(0);
small_array.insert_sorted(item);
least_found_value = small_array.get(0).value;
}
}
small_array可能是一个Object []和内环可与交换,而不是实际删除和插入到一个数组来进行。