Heaps & Intervals

Two patterns that show up constantly: a heap for top-K / streaming / merging, and sort-then-sweep for interval problems.

heappriority-queueintervalssorting

Heap = priority queue

A binary heap gives O(log n) push/pop and O(1) peek of the min (or max). Reach for it whenever you repeatedly need the current extreme of a changing set.

Top-K with a size-K heap

To find the K largest, keep a min-heap of size K: push each element, and if the heap exceeds K, pop the smallest. What remains is the top K.

Python
import heapq

def k_largest(nums, k):
    h = []
    for x in nums:
        heapq.heappush(h, x)
        if len(h) > k:
            heapq.heappop(h)     # drop the smallest so far
    return h                      # the k largest (unordered)
# Time O(n log k), Space O(k) — beats sorting's O(n log n) when k << n

Other heap classics

  • Merge K sorted lists — push the head of each list; pop the min, push its successor. O(N log K).
  • Streaming median — a max-heap of the lower half + a min-heap of the upper half, kept balanced; median is the top(s). O(log n) per insert.
Top-K: heap vs sort vs quickselect

Sorting is O(n log n). A size-K heap is O(n log k) — better when k is small. Quickselect finds the kth element in O(n) average (O(n²) worst) and partitions around it. Mention all three and pick by constraints; the heap also handles streaming input, which sort/quickselect can't.

Watch it run

The same heap shown both ways at once: the flat array that's actually in memory, and the complete binary tree it encodes. Watch values sift up on push and sift down after extract-min.

Min-heap — push all, then extract-mintime O(log n) per opspace O(1) aux
(empty)

1/22Min-heap stored in an array: parent of i is ⌊(i−1)/2⌋, children are 2i+1 and 2i+2. Parent ≤ children, always.

Intervals = sort first, then sweep

Watch the sweep in action — after sorting by start, every new interval either overlaps the block being built (stretch it) or starts a fresh one (gap). One pass, no backtracking:

Merge overlapping intervalstime O(n log n)space O(n)
02468101214161820132681015181720merged

1/8Merge every overlapping pair into one block (think: calendar busy-bars). Unsorted, overlaps are scattered everywhere…

Almost every interval problem starts by sorting by start (or end), then making one pass.

Python
# Merge overlapping intervals.
def merge(intervals):
    intervals.sort(key=lambda iv: iv[0])
    out = [intervals[0]]
    for s, e in intervals[1:]:
        if s <= out[-1][1]:           # overlaps the last merged interval
            out[-1][1] = max(out[-1][1], e)
        else:
            out.append([s, e])
    return out
# Time O(n log n) for the sort, then O(n)

For "max concurrent intervals" (meeting rooms), sweep the sorted start/end events or use a min-heap of end times. Sort by end time for greedy "max non-overlapping intervals".

Practice — climb the ladder

Heap trigger words: "k largest", "k closest", "median of a stream". Interval trigger: sort by start (merge) or by end (scheduling), then sweep.

Practice ladder: Heaps & Intervals0/9 solved

Climb in order — every rung assumes the one above it. Solve on LeetCode, then tick it here; progress is saved on this device.

Warm-up

heap API fluency
  1. A min-heap of size k — the counterintuitive trick behind every top-k problem.

  2. Repeated extract-max — pure heap mechanics, nothing else in the way.

Core

top-k + the two interval sorts
  1. Heap of size k vs quickselect — know both and say the trade-off.

  2. Top-k with a comparator — same skeleton, custom distance.

  3. Sort by START, extend the current block — the merge half of interval thinking.

  4. Sort by END, keep what finishes earliest — the greedy scheduling half.

  5. Greedy by frequency with a heap — capacity math meets extract-max.

Stretch

two heaps, opposing directions
  1. Max-heap + min-heap balanced around the middle — the two-heap pattern.

  2. Sort-by-end greedy again — proof you recognize the pattern in costume.