A heap is a special tree-based data structure that allows fast access to the minimum or maximum element.
Whenever a problem says:
Think HEAP immediately.
A heap is a complete binary tree that satisfies the heap property.
Example:
1
/ \
3 5
/ \
7 9
Example:
9
/ \
7 5
/ \
3 1
Heaps are usually implemented using arrays.
For index i:
2i + 12i + 2(i - 1) / 2This avoids pointer overhead.
Steps:
void insert(int x){
heap[size] = x;
int i = size;
size++;
while(i > 0 && heap[(i-1)/2] > heap[i]){
swap(i, (i-1)/2);
i = (i-1)/2;
}
}
Steps:
int extractMin(){
int min = heap[0];
heap[0] = heap[--size];
heapify(0);
return min;
}
Heapify is the process of restoring heap property.
void heapify(int i){
int smallest = i;
int left = 2*i + 1;
int right = 2*i + 2;
if(left < size && heap[left] < heap[smallest])
smallest = left;
if(right < size && heap[right] < heap[smallest])
smallest = right;
if(smallest != i){
swap(i, smallest);
heapify(smallest);
}
}
Time complexity: O(log n)
Convert array into heap in O(n) time.
for(int i = n/2 - 1; i >= 0; i--)
heapify(i);
Important interview fact:
Building heap is O(n), not O(n log n)
A Priority Queue is an abstract data structure where:
Internally implemented using heap.
PriorityQueue<Integer> pq = new PriorityQueue<>(); // Min heap
PriorityQueue<Integer> maxPQ = new PriorityQueue<>(Collections.reverseOrder());
Operations:
Find K largest elements from an array.
PriorityQueue<Integer> pq = new PriorityQueue<>();
for(int x : arr){
pq.add(x);
if(pq.size() > k)
pq.poll();
}
Heap size never exceeds K
Time complexity: O(n log k)
Find K elements with highest frequency.
Map<Integer, Integer> map = new HashMap<>();
for(int x : nums)
map.put(x, map.getOrDefault(x, 0) + 1);
PriorityQueue<int[]> pq = new PriorityQueue<>(
(a, b) -> a[1] - b[1]
);
for(int key : map.keySet()){
pq.add(new int[]{key, map.get(key)});
if(pq.size() > k)
pq.poll();
}
Merge K sorted linked lists into one.
PriorityQueue<ListNode> pq = new PriorityQueue<>(
(a, b) -> a.val - b.val
);
for(ListNode head : lists)
if(head != null)
pq.add(head);
while(!pq.isEmpty()){
ListNode node = pq.poll();
curr.next = node;
curr = curr.next;
if(node.next != null)
pq.add(node.next);
}
Time: O(n log k)
| Scenario | Use |
|---|---|
| Single query | Quickselect |
| Multiple queries | Heap |
| Streaming data | Heap |
| Worst-case safe | Heap |
Heaps are heavily used in scheduling.
Given tasks with deadlines and profit, maximize profit.
Approach:
for(Task t : tasks){
pq.add(t.profit);
if(pq.size() > t.deadline)
pq.poll();
}
Find minimum meeting rooms required.
Approach:
PriorityQueue<Integer> pq = new PriorityQueue<>();
pq.add(intervals[0].end);
for(int i = 1; i < n; i++){
if(intervals[i].start >= pq.peek())
pq.poll();
pq.add(intervals[i].end);
}