Heaps & Priority Queues

Med

A heap is a complete binary tree with a strict parent-child ordering rule. In a min-heap, parents are always smaller than children; in a max-heap, parents are always larger. This lets you repeatedly get the "best next" item in O(1) and update the heap in O(log n).

Interactive Visualization

Heap (Tree View)parent = floor((i-1)/2)
50
30
40
10
20
Array Representation
50
[0]
30
[1]
40
[2]
10
[3]
20
[4]
insertStart with max heap [50, 30, 40, 10, 20]. Insert 60.
1 / 6
Key Insight: Insert adds at the end and "bubbles up" by swapping with parent until heap property is satisfied. O(log n) since tree height is log n.

Time Complexity

OperationAverageWorst
InsertO(log n)O(log n)
Extract min/maxO(log n)O(log n)
PeekO(1)
Build from listO(n)

Key Points

  • Parent index = floor((i - 1) / 2), children = 2i + 1 and 2i + 2
  • Min-heap gives fast smallest-value retrieval (peek)
  • Max-heap gives fast largest-value retrieval (peek)
  • Insert and extract both rebalance along one root-to-leaf path
  • Ideal for top-k / streaming selection problems
  • Priority queues are heaps used with custom priority keys

Code Examples

Min-Heap Operations

class MinHeap {
  constructor() {
    this.values = []
  }

  insert(value) {
    this.values.push(value)
    this.bubbleUp()
  }

  peek() {
    return this.values[0]
  }

  extractMin() {
    if (this.values.length === 0) return null
    if (this.values.length === 1) return this.values.pop()

    const min = this.values[0]
    this.values[0] = this.values.pop()
    this.bubbleDown()
    return min
  }

  bubbleUp() {
    let index = this.values.length - 1
    while (index > 0) {
      const parentIndex = Math.floor((index - 1) / 2)
      if (this.values[parentIndex] <= this.values[index]) break

      ;[this.values[parentIndex], this.values[index]] = [this.values[index], this.values[parentIndex]]
      index = parentIndex
    }
  }

  bubbleDown() {
    let index = 0
    const n = this.values.length

    while (true) {
      const leftIndex = index * 2 + 1
      const rightIndex = index * 2 + 2
      let smallestIndex = index

      if (leftIndex < n && this.values[leftIndex] < this.values[smallestIndex]) {
        smallestIndex = leftIndex
      }
      if (rightIndex < n && this.values[rightIndex] < this.values[smallestIndex]) {
        smallestIndex = rightIndex
      }
      if (smallestIndex === index) break

      ;[this.values[index], this.values[smallestIndex]] = [this.values[smallestIndex], this.values[index]]
      index = smallestIndex
    }
  }
}

const heap = new MinHeap()
heap.insert(5)
heap.insert(2)
heap.insert(8)
heap.insert(1)

heap.peek() // 1
heap.extractMin() // 1
heap.extractMin() // 2

Insert and extract are each O(log n); peek is O(1).

Top K Frequent with Heap Concept

// Count frequencies first
const freq = new Map()
for (const num of [1, 2, 2, 3, 3, 3]) {
  freq.set(num, (freq.get(num) || 0) + 1)
}

// Turn each [value, frequency] pair into a candidate
// Keep only top 2 elements in a min-heap of fixed size
const pairs = Array.from(freq.entries())
console.log('Pairs:', pairs)
// [[1,1], [2,2], [3,3]]

// If we only need k elements, keep a small heap and drop low frequency items quickly

Heaps are useful when you only need the top-k frequencies, not full sorted order.

Merge K Sorted Lists Idea

// Push each list head into a min-heap
// Extract the smallest, then push next node from that same list.
// Repeat until heap is empty.

function explainMergeKSortedLists() {
  const example = [
    [1, 4, 5],
    [1, 3, 4],
    [2, 6],
  ]

  console.log('Input lists:', example)
  console.log('Keep heap of current smallest heads: 1, 1, 2')
  console.log('Extract 1, then add 4 from first list')
  console.log('Extract 1, then add 3 from second list')
  console.log('... and so on')
}

explainMergeKSortedLists()

This pattern shows why heaps excel at repeatedly selecting the current global minimum from many sorted sources.

Common Mistakes

  • Using O(n log n) sort when a heap of size k gives O(n log k)
  • Swapping wrong child when bubbling down (breaks heap property)
  • Forgetting to rebalance after extract
  • Building custom compare rules when built-in library already exists in some languages
  • Confusing min-heap and max-heap priority direction in examples

Interview Tips

  • Start by clarifying whether you need smallest-first or largest-first
  • Explain why repeated global selection is exactly what heaps optimize
  • Track heap size if you only need top k (not the full structure)
  • For coding interviews, write parent/child helper methods to avoid index mistakes

Practice Problems

Related Concepts