我正在寻求在网页上根据各自的权重显示固定数量的项目(由Integer
表示)。找到这些物品的清单几乎可以是任何尺寸。
首先想到的解决方案是执行Collections.sort()
并通过List
逐个获取项目。是否有一个更优雅的解决方案虽然可以用来准备前八项?
答案 0 :(得分:6)
去Collections.sort(..)
。它足够有效。
此算法可提供有保证的n log(n)性能。
如果您知道列表的某些独特属性,可以尝试为您的具体案例实现更高效的,但这是不合理的。此外,如果您的列表来自数据库,例如,您可以LIMIT
它&在那里订购而不是代码。
答案 1 :(得分:5)
您的选择:
执行线性搜索,保持沿途找到的前N个权重。 如果由于某种原因,您无法在显示页面之间重复使用排序结果(例如列表正在快速变化),这应该比排序长度列表更快。
更新:我认为线性搜索必须比排序更好。有关更好的选择算法,请参阅维基百科文章“Selection_algorithm - Selecting k smallest or largest elements”。
手动维护按重量顺序排序的List
(原始的或平行的)。您可以使用Collections.binarySearch()之类的方法来确定每个新项目的插入位置。
维护List
(原始的或平行的)按重量顺序排序,在每次修改,批量修改或显示之前调用Collections.sort()(可能保留修改标记)避免对已排序的列表进行排序。)
使用维护已排序权重顺序的数据结构:priority queue,tree set等。您还可以创建自己的数据结构。
手动维护前N个项目的第二个(可能是重量排序的)数据结构。只要修改原始数据结构,就会更新此数据结构。您可以创建自己的数据结构来将原始列表和这个“前N个缓存”包装在一起。
答案 2 :(得分:3)
您可以使用max-heap。
如果您的数据来自数据库,请在该列上添加索引并使用ORDER BY和TOP或LIMIT仅获取您需要显示的记录。
答案 3 :(得分:3)
答案 4 :(得分:3)
使用dollar:
List<Integer> topTen = $(list).sort().slice(10).toList();
不使用美元,您应sort()
使用Collections.sort()
,然后使用list.sublist(0, n)
获取前n项。
答案 5 :(得分:2)
既然你说从中提取这些前N个的项目列表可能是任何大小的,所以可能很大我假设,我会增加上面的简单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());
这里的堆(最小堆)的大小至少有限。没有必要从你的所有物品中堆出来。
答案 6 :(得分:1)
不,不是真的。至少不使用Java的内置方法。
有一些聪明的方法可以比列表O(n*log(n))
更快地从列表中获取最多(或最低)的N个项目,但这需要您手动编写此解决方案。如果项目数量保持相对较低(不超过几百),使用Collections.sort()
对其进行排序,然后获取前N个数字是IMO的方法。
答案 7 :(得分:1)
取决于多少。让我们将n定义为键的总数,将m定义为您想要显示的数字
对整个事物进行排序:O(nlogn)
每次扫描阵列以获得下一个最高数字:O(n*m)
所以问题是 - n与m之间的关系是什么?
如果m < log n
,扫描效率会更高
否则,m >= log n
,这意味着排序会更好。 (因为对于m = log n
的边缘情况它实际上并不重要,但排序也会给你带来好处,好吧,排序数组,总是很好。
答案 8 :(得分:0)
如果列表的大小为N,并且要检索的项目数为K,则需要在列表上调用Heapify,该列表将列表(必须是可索引的,例如数组)转换为优先级队列。 (参见http://en.wikipedia.org/wiki/Heapsort)中的heapify函数
检索堆顶部的项目(最大项目)需要O(lg N)时间。所以你的总时间是:
O(N + k lg N)
假设k远小于N,则优于O(N lg N)。
答案 9 :(得分:0)
如果不能选择保留已排序的数组或使用不同的数据结构,则可以尝试以下方法。 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 [],内部循环可以通过交换完成,而不是实际删除和插入数组。