๐Ÿ”

Heap / Priority Queue

Use min/max heaps for top-K problems, scheduling, and efficient repeated minimum extraction.

0 Problems2-3 hours

Overview

A heap is a complete binary tree satisfying the heap property: every node is โ‰ค (min-heap) or โ‰ฅ (max-heap) its children. It enables O(log n) insert and O(1) peek at the min/max. Most languages provide a priority queue built on a heap.

Complexity Summary

Time Complexity

Insert O(log n) ยท Peek O(1) ยท Extract O(log n) ยท Build O(n)

Space Complexity

O(n)

Key Patterns & Techniques

Learn the core patterns in this topic. Each block explains when to use the pattern, the intuition behind it, and a compact code example.

1

Top K Elements with Min-Heap

Concept

Use this when you need the k largest elements from a stream or array

Why It Works

Maintain a min-heap of exactly size k. Push each new element; if the heap exceeds k, pop the minimum. After processing all elements, the heap contains the k largest. The top of the min-heap is the kth largest overall.

Pattern Example
Problem

Problem Kth Largest Element in a Stream. Push each number; if size > k pop the smallest; the heap top is always the kth largest. class KthLargest { constructor(k, nums) { this.k = k; this.heap = new MinHeap(); for (const n of nums) this.add(n); } add(val) { this.heap.push(val); if (this.heap.size > this.k) this.heap.pop(); return this.heap.peek(); } }

Implementation
// Top K elements โ€” Kth Largest Element in an Array
// JavaScript lacks a built-in heap; we sort and take the top k here
function findKthLargest(nums, k) {
  nums.sort((a, b) => b - a);
  return nums[k - 1];
}
// For stream-based: maintain a sorted structure of size k
class KthLargestStream {
  constructor(k, nums) { this.k = k; this.data = nums.sort((a,b) => a-b).slice(-k); }
  add(val) {
    let lo = 0, hi = this.data.length;
    while (lo < hi) { const mid = (lo+hi)>>1; if (this.data[mid] < val) lo=mid+1; else hi=mid; }
    this.data.splice(lo, 0, val);
    if (this.data.length > this.k) this.data.shift();
    return this.data[0];
  }
}
Practice questions for this pattern
2

K Most Frequent Elements

Concept

Use this when you need the k items with the highest frequency from a collection

Why It Works

First build a frequency map, then use a min-heap of size k keyed on frequency. Push each (frequency, element) pair; if the heap exceeds k, pop the least frequent.

Pattern Example
Problem

Problem Top K Frequent Elements. Count frequencies with a map, then maintain a min-heap of size k on frequency values to find the k most frequent.

Implementation
// K most frequent โ€” Top K Frequent Elements
function topKFrequent(nums, k) {
  const freq = new Map();
  for (const n of nums) freq.set(n, (freq.get(n) ?? 0) + 1);
  return [...freq.entries()]
    .sort((a, b) => b[1] - a[1])
    .slice(0, k)
    .map(e => e[0]);
}
Practice questions for this pattern
3

Merge K Sorted Lists

Concept

Use this when K sorted lists must be merged into a single sorted output

Why It Works

Insert the head of each list into a min-heap keyed on node value. Repeatedly extract the minimum node, append it to the result, and push its next node (if any) into the heap. The heap always holds at most K nodes at once.

Pattern Example
Problem

Problem Merge K Sorted Lists. Initialize the heap with the first node of each list; each extraction produces the next merged node.

Implementation
// Merge K sorted lists โ€” simulate with sorted array (no built-in heap)
function mergeKLists(lists) {
  const dummy = new ListNode(0);
  let curr = dummy;
  const nodes = [];
  for (const head of lists) { let n = head; while (n) { nodes.push(n.val); n = n.next; } }
  nodes.sort((a, b) => a - b);
  for (const v of nodes) { curr.next = new ListNode(v); curr = curr.next; }
  return dummy.next;
}
Practice questions for this pattern
4

Find Median from Data Stream (Two Heaps)

Concept

Use this when you need the running median as numbers are inserted one at a time

Why It Works

Maintain two heaps: a max-heap for the lower half and a min-heap for the upper half. After each insertion, rebalance so the sizes differ by at most one. The median is either the top of the larger heap or the average of both tops.

Pattern Example
Problem

Problem Find Median from Data Stream. Lower max-heap gets new element first, then the root is moved to the upper min-heap; rebalance sizes if needed. class MedianFinder { addNum(num) { this.lower.push(num); this.upper.push(this.lower.pop()); if (this.upper.size > this.lower.size) this.lower.push(this.upper.pop()); } findMedian() { return this.lower.size > this.upper.size ? this.lower.peek() : (this.lower.peek() + this.upper.peek()) / 2; } }

Implementation
// Running median โ€” two heaps (simulate with sorted array)
class MedianFinder {
  constructor() { this.data = []; }
  addNum(num) {
    let lo = 0, hi = this.data.length;
    while (lo < hi) { const mid=(lo+hi)>>1; if(this.data[mid]<num) lo=mid+1; else hi=mid; }
    this.data.splice(lo, 0, num);
  }
  findMedian() {
    const n = this.data.length;
    return n % 2 === 0
      ? (this.data[n/2-1] + this.data[n/2]) / 2
      : this.data[Math.floor(n/2)];
  }
}
Practice questions for this pattern
5

K Closest Points to Origin

Concept

Use this when you need the K points nearest to the origin from a list of points, using Euclidean distance squared to avoid floating point

Why It Works

Maintain a max-heap of size k keyed on distance; pop the farthest point when the heap exceeds k. What remains are the k closest.

Pattern Example
Problem

Problem K Closest Points to Origin. Push (dist, point); when size > k pop the max-dist entry; the heap holds the k closest.

Implementation
// K closest points to origin โ€” sort by distance squared
function kClosest(points, k) {
  return points
    .sort((a, b) => (a[0]*a[0]+a[1]*a[1]) - (b[0]*b[0]+b[1]*b[1]))
    .slice(0, k);
}
Practice questions for this pattern
6

Task Scheduling with Heap (Reorganize String)

Concept

Use this when tasks or characters must be scheduled such that the most frequent items are spread out

Why It Works

Use a max-heap to always pick the item with the highest remaining count, and a cooldown queue to hold items that are in their cooldown period. This greedy-with-heap approach produces the optimal arrangement.

Pattern Example
Problem

Problem Reorganize String. Always place the most frequent unused character; if the previous character is now off cooldown, return it to the heap.

Implementation
// Task scheduling โ€” Reorganize String (greedy even-index fill)
function reorganizeString(s) {
  const freq = new Array(26).fill(0);
  for (const c of s) freq[c.charCodeAt(0) - 97]++;
  const maxFreq = Math.max(...freq);
  if (maxFreq > Math.ceil(s.length / 2)) return "";
  const sorted = freq.map((f, i) => [f, i]).sort((a, b) => b[0] - a[0]);
  const res = new Array(s.length);
  let idx = 0;
  for (const [f, c] of sorted) {
    for (let i = 0; i < f; i++) {
      if (idx >= s.length) idx = 1;
      res[idx] = String.fromCharCode(c + 97);
      idx += 2;
    }
  }
  return res.join("");
}
Practice questions for this pattern
DSA Practice Online - 150+ Coding Interview Questions | LeetCode Alternative | InstaMock - AI Mock Interview