๐Ÿณ IntuitiveFE
Login
โ† All concepts

Heap

โฑ๏ธ ~3-minute bite ยท solve the sandbox to master

0%lesson
๐Ÿง’

5-Year-Old Metaphor

โ€” The physical, real-world picture. No jargon.

๐Ÿฅ A hospital waiting room where the sickest patient is always seen first โ€” but the other seats aren't sorted.

The core idea

A heap is a binary tree with one rule: every parent is more extreme than its children. In a min-heap, every parent is smaller (sickest first). In a max-heap, every parent is larger (highest salary at the top of the org chart).

The top always holds the extreme value. But the rest? Not fully sorted โ€” just roughly ordered. That's the trade-off: you get O(log n) access to the extreme element without paying the O(n log n) cost of a full sort.

Min-Heap

Hospital triage: root = sickest patient. Every nurse only needs to look at the top. When a patient is treated, the next sickest bubbles up automatically.

Use for: Dijkstra, A*, task schedulers, finding kth smallest

Max-Heap

Corporate org chart: root = highest earner. Every manager earns more than their direct reports. Useful when you want the maximum fast.

Use for: HeapSort, finding kth largest, streaming median

Why an array, not a tree?

A complete binary tree maps perfectly to an array with no pointers needed. For index i:

left child
2i + 1
right child
2i + 2
parent
โŒŠ(i-1)/2โŒ‹

This is 0-based. Some textbooks use 1-based (left = 2i, right = 2i+1, parent = โŒŠi/2โŒ‹). The interview bug: mixing up 0-based and 1-based index math.

๐ŸŽ›๏ธ

Interactive Sandbox

โ€” Move something, see it react instantly.
How to use: pick a pattern below, then step through the algorithm. The array shows heap storage; the tree shows the same data as a binary tree. Amber = comparing, violet = swapping, emerald = settled. Explore all 5 patterns to master.

Array representation

1
[0]
3
[1]
5
[2]
7
[3]
9
[4]
left child of i โ†’ 2i+1
right child of i โ†’ 2i+2
parent of i โ†’ โŒŠ(i-1)/2โŒ‹

Tree visualization

1
3
7
9
5
[done]Min-heap state: [1,3,5,7,9]. We want to insert 2.

โš ๏ธ Gotcha

0-based index math: parent = Math.floor((i-1)/2). Not (i/2). Off-by-one breaks the whole tree.

๐Ÿ’ก Insight

Sift-up only travels the height of the tree โ€” O(log n). The rest of the heap stays untouched.

Step 1 / 6
๐ŸŽฏ

Challenge

Explore all 5 heap patterns. (1 / 5 explored)

Try it
๐ŸŽฏ

Why Should I Care?

โ€” The exact interview question + the bug it kills.

Q: Heap vs sorted array for priority queue?

A sorted array gives O(1) access to the min/max โ€” just read the first or last element. But insertion is O(n) because you must shift elements to maintain order. A heap gives O(log n) insert and O(log n) extract. When you're doing many insertions and extractions (a scheduler, Dijkstra's open set), the heap wins massively.

Q: Why O(n) build heap but O(n log n) insert n times?

Building bottom-up (heapify): most nodes are near the leaves where sift-down travels height 0 or 1. Only the root travels log n. The geometric sum works out to O(n).

Inserting one-by-one: every insertion can sift up through the full height โ€” O(log n) each ร— n insertions = O(n log n). Same result, different constant. For large n, bottom-up is 2ร— faster in practice.

Q: When to use heap vs sort?

Sort everything when you need global order. Use a heap when you only need the top k elements, or when data arrives as a stream and you can't sort ahead of time. Heap + k = O(n log k). Full sort = O(n log n). When k is small (e.g. k=10 from 10M items), heap is orders of magnitude faster.

Bug: 0-based vs 1-based index math

js
1// 0-based (standard JS arrays) โœ…
2const left = 2 * i + 1;
3const right = 2 * i + 2;
4const parent = Math.floor((i - 1) / 2);
5ย 
6// 1-based (some textbooks) โ€” mixing these is the bug โŒ
7// left = 2*i, right = 2*i+1, parent = Math.floor(i/2)
8// If your heap gives wrong answers, check this first.

Complexity reference

OperationTimeSpace
Insert (sift-up)O(log n)O(1)
Extract min/maxO(log n)O(1)
Peek min/maxO(1)O(1)
Build heap (heapify)O(n)O(1)
Heap sortO(n log n)O(1)
Kth largest (heap of size k)O(n log k)O(k)
๐Ÿ”ฌ

The Deep Dive

โ€” Spec refs, engine internals, the minutiae.

Binary heap index math โ€” the full picture

A complete binary tree of height h has 2^(h+1) - 1 nodes. Nodes at depth d start at index 2^d - 1 (0-based). Leaves occupy roughly half the array (indices โŒŠn/2โŒ‹ to n-1). This is why heapify starts at index โŒŠn/2โŒ‹ - 1 and works backwards โ€” it skips all the leaves, which have nothing to sift.

Sift-up vs sift-down โ€” when each is used

Sift-up

  • Used on INSERT: new element appended at end, bubbles toward root
  • Compare with parent only, single path to root
  • At most log n comparisons

Sift-down

  • Used on EXTRACT and HEAPIFY: root replaced, falls toward leaves
  • Compare with both children, pick the smaller (min-heap)
  • At most 2 log n comparisons (both children each level)

Sift-down does twice the comparisons โ€” important for cache analysis. HeapSort uses sift-down exclusively, which is why its constant is larger than MergeSort's.

Priority queue in JavaScript (no built-in)

JS/TS has no built-in heap. You implement one with an array. The minimal viable min-heap:

ts
1class MinHeap {
2 private h: number[] = [];
3ย 
4 push(val: number) {
5 this.h.push(val);
6 this._siftUp(this.h.length - 1);
7 }
8ย 
9 pop(): number {
10 const top = this.h[0];
11 const last = this.h.pop()!;
12 if (this.h.length > 0) {
13 this.h[0] = last;
14 this._siftDown(0);
15 }
16 return top;
17 }
18ย 
19 peek() { return this.h[0]; }
20 size() { return this.h.length; }
21ย 
22 private _siftUp(i: number) {
23 while (i > 0) {
24 const p = (i - 1) >> 1; // same as Math.floor((i-1)/2)
25 if (this.h[p] <= this.h[i]) break;
26 [this.h[p], this.h[i]] = [this.h[i], this.h[p]];
27 i = p;
28 }
29 }
30ย 
31 private _siftDown(i: number) {
32 const n = this.h.length;
33 while (true) {
34 let s = i;
35 const l = 2*i+1, r = 2*i+2;
36 if (l < n && this.h[l] < this.h[s]) s = l;
37 if (r < n && this.h[r] < this.h[s]) s = r;
38 if (s === i) break;
39 [this.h[i], this.h[s]] = [this.h[s], this.h[i]];
40 i = s;
41 }
42 }
43}

Real uses in production

  • Dijkstra / A* โ€” min-heap on (cost, node) drives the frontier. Without it, you'd scan all unvisited nodes each step: O(Vยฒ) vs O((V+E) log V).
  • Task schedulers โ€” Node.js's event loop, OS process scheduling, React's concurrent scheduler all use priority queues. Tasks with highest priority are dequeued first.
  • Streaming median โ€” maintain two heaps: max-heap of the lower half, min-heap of the upper half. Keep them balanced. Median is always the root of one or the average of both. O(log n) per insert, O(1) median query.
  • Top-k reporting โ€” leaderboards, trending topics, log anomaly detection. Min-heap of size k: discard anything smaller than the current kth largest.

Fibonacci heap โ€” theory vs practice

Fibonacci heaps achieve decrease-key in O(1) amortized, making Dijkstra O(E + V log V) vs O((V+E) log V) with a binary heap. Theoretically superior on dense graphs.

In practice? Rarely used. The constant factors are enormous โ€” pointer-heavy, cache-unfriendly, complex to implement correctly. For most real graphs, a binary heap or even a simple array beats a Fibonacci heap due to cache behavior. Know the theory for interviews; use binary heap in code.

Related patterns

  • Two Heaps โ€” streaming median, task partitioning
  • Monotonic Deque โ€” sliding window maximum in O(n) โ€” different from heap but similar "always have the extreme fast" goal
  • Segment Tree โ€” range queries beyond just min/max (sum, GCD) with O(log n) update
  • Order Statistics Tree โ€” find kth element in O(log n) for a fully dynamic set
๐ŸŽค

Interview Questions

โ€” Real questions from real interviews โ€” with answers.

A heap is a complete binary tree satisfying the heap property โ€” insert and extract-min/max are O(log n); peek is O(1).

Maintain a min-heap of size k โ€” the root is always the k-th largest seen so far.

Push the head of each list into a min-heap, then repeatedly extract the min and advance that list's pointer.

Max-heap for the lower half, min-heap for the upper half โ€” balance them after each insert so sizes differ by at most 1.

Heap is O(log n) insert/extract and O(1) peek โ€” BST adds O(log n) arbitrary delete and ordered traversal but with higher constants.

๐ŸŽฎ

Memory Game

โ€” Quick quiz โ€” lock the concept in long-term memory.
1/4

What is the time complexity of extracting the minimum from a min-heap?