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.
Answer from user2357112 on Stack OverflowNope. 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.
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. Each remove costs you O(log(n)) but you have also figured that one out, hence the question.
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. The asymptotic complexity of a partial sort is 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).
Java's PriorityQueue, like most priority queues, is implemented with a heap.
A heap is a data structure that maintains only the property that all parents are less than their children, or all parents are greater than their children. There is no inherent ordering among children.
Thus, the only way to find the tail would be to do a linear search among the bottom layer, which costs O(n) time for a size n priority queue.
Yes, but the at the cost of extra space complexity:
PriorityQueue<Integer> pqNew = new PriorityQueue<>(java.util.Collections.reverseOrder());
Now add the elements of your PriorityQueue into this pqNew.
Therefore, pqNew.peek() will give you the required answer i.e. the tail element of your original PriorityQueue.
Because you are polling first
System.out.println(pq.poll() + ":" + pq.peek());
As it is a priority queue elements are stored as
carrot -> banana -> apple
When you poll() you get apple and is removed from queue. After which head of queue is banana which is exactly what you get when you peek().
please look at the example 2 in updated question. Sorting is strange
It's just what you don't expect. You can see the documentation
The Iterator provided in method iterator() is not guaranteed to traverse the elements of the priority queue in any particular order. If you need ordered traversal, consider using Arrays.sort(pq.toArray()).
You will understand this better if you read priority heap data structure which java priority queue use. You should use poll(), peek() methods to get ordered data.
You are using PriorityQueue and not java.util.Queue (Regular Queue) PriorityQueue sorts the elements depending on the implementation of the Comparable::compareTo() method which is a natural ordering (alphabetical order) for String.class.
Hence, the elements in your queue would be apple-banana-carrot. The output is as expected