[英]in Java, How do I peek() the top k elements in a PriorityQueue ?
I see in the documentation, that PriorityQueue.peek() gives me access to the head of the queue in O(1), but what if I need access to the k top elements in the queue ? 我在文档中看到, PriorityQueue.peek()使我可以访问O(1)中的队列头,但是如果我需要访问队列中的k个top元素怎么办? I would use
poll()
k times, but that takes O(log(N)) , is there a way to do it in constant time ? 我会用
poll()
k次,但这需要O(log(N)),有没有办法在固定时间内做到呢?
Nope. 不。 If you could do it in constant time, you could do a comparison sort in linear time by heapifying an array and then finding the top N items, where N is all of them.
如果您可以在固定时间内执行此操作,则可以通过在数组中堆积数组然后找到前N个项(其中N个都是全部)来在线性时间内进行比较排序。
It's not possible to do it in constant time. 不可能在恒定时间内进行。 If your data is already in a
PriorityQueue
, removing the top k elements one by one is the best you can do. 如果您的数据已经在
PriorityQueue
,则最好的方法是一个接一个地删除前k个元素。 Each remove costs you O(log(n))
but you have also figured that one out, hence the question. 每次删除都会花费
O(log(n))
但您也已经弄清楚了,因此是个问题。
However, if you are not forced to use a PriorityQueue
, then you can do a partial sort on a list and retrieve the top k elements. 但是,如果不被迫使用
PriorityQueue
,则可以对列表进行部分排序并检索前k个元素。 The asymptotic complexity of a partial sort is O(n*log(k))
. 部分排序的渐近复杂度为
O(n*log(k))
。 It can be executed faster than the PriorityQueue
approach if we also take into account the cost of setting up the priority queue, see Selecting top k items from a list efficiently in Java / Groovy (select the top 5 elements from a list of 10 million, PriorityQueue 300ms vs. partial sort 170ms). 如果我们还考虑设置优先级队列的成本,它的执行速度可以比
PriorityQueue
方法快,请参阅在Java / Groovy中从列表中高效选择前k个项目 (从1000万个列表中选择前5个元素, PriorityQueue 300毫秒与部分排序170毫秒)。
It can be done in O(klogk)
time and O(k)
additional space if the input is represented as an indexed sequence in heap order. 如果输入以堆顺序表示为索引序列,则可以在
O(klogk)
时间和O(k)
附加空间中完成。 If k << n
, that's a very good improvement. 如果
k << n
,这是一个很好的改进。
static List <Integer> kLargest(List<Integer> xs, int k) {
if (k <= 0) return Collections.emptyList();
PriorityQueue<Map.Entry<Integer, Integer>> pq =
new PriorityQueue<>(Comparator.comparingInt(Map.Entry::getValue));
pq.add(new SimpleImmutableEntry<>(0, xs.get(0)));
List<Integer> result = new ArrayList<>();
for (int i = 0; i < k; i++) {
Map.Entry <Integer, Integer> max = pq.remove();
result.add(max.getValue());
int j = max.getKey();
int left = 2 * j + 1;
int right = 2 * j + 2;
if (left < xs.size()) pq.add(new SimpleImmutableEntry<>(left, xs.get(left)));
if (right < xs.size()) pq.add(new SimpleImmutableEntry<>(right, xs.get(right)));
}
return result;
}
The question is, how to get the input in heap order. 问题是,如何按堆顺序获取输入。 If you create your own
PriorityQueue
class, you'll obviously have access to the internal array. 如果创建自己的
PriorityQueue
类,则显然可以访问内部数组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.