For example, given a List of Integer List<Integer> list = Arrays.asList(5,4,5,2,2)
, how can I get a maxHeap
from this List in O(n)
time complexity?
The naive method:
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder()); for (Integer i : list) { maxHeap.offer(i); }
However, the time complexity is O(nlogn)
.
We can trigger the heapify method by using the following constructor:
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(list);
The time complexity is O(n)
. However, it forces me to use the natural order which is the minHeap.
My Question:
How can I construct a PriorityQueue by heapifying a Collection with custom Comparator?
Ref: Java doc of PriorityQueue
PS:
@user207421
Heapify algorithm can transform any unsorted array into a heap in O(n)
time, not O(nlogn)
. There are many articles about heapify, also in CLRS’s Introduction to Algorithms Page 159, build a heap from any unsorted array is O(n)
. And heap is also not a sorted array. It’s a complete tree with heap property which can be encoded in array.
Advertisement
Answer
If you don’t mind some hack
According to the java doc of PriorityQueue(PriorityQueue)
Creates a PriorityQueue containing the elements in the specified priority queue. This priority queue will be ordered according to the same ordering as the given priority queue.
So we can extend PriorityQueue
as CustomComparatorPriorityQueue
to hold the desired comparator and the Collection we need to heapify. Then call new PriorityQueue(PriorityQueue)
with an instance of CustomComparatorPriorityQueue
.
Below is tested to work in Java 15.
import java.util.*; public class CustomComparatorPriorityQueue<T> extends PriorityQueue<T> { private Collection<T> wrapped; public static <U> PriorityQueue<U> create(Collection<U> wrapped, Comparator<U> custom) { return new PriorityQueue<U>(new CustomComparatorPriorityQueue<>(wrapped, custom)); } private CustomComparatorPriorityQueue(Collection<T> wrapped, Comparator<T> custom) { super(custom); this.wrapped = wrapped; } @Override public Object[] toArray() { return wrapped.toArray(); } public static void main(String[] args) { List<Integer> a = Arrays.asList(3, 6, 4, 8, 1, 9); PriorityQueue<Integer> pq = CustomComparatorPriorityQueue.create(a, Comparator.<Integer>naturalOrder().reversed()); Integer b; while ((b = pq.poll()) != null) { System.out.println(b); } } // Override to don't allow other purpose... }