latency.lab
Algorithms · Topic 20

Advanced Synthesis

Level: capstoneTool: Combining techniques from every earlier topicTime: ~100 min

By the end you can

Nineteen topics in, you've built a toolbox: two pointers, sliding windows, heaps, union-find, DP over sequences and grids, greedy, intervals, sweep lines, tries, graphs. Nothing in this final topic is a brand-new idea in isolation — what's new is that every problem here needs two or more of those tools working together, or needs a familiar tool pushed somewhere it hasn't gone before. This is the capstone, and it's deliberately the hardest topic in the roadmap: if a problem here feels approachable, it's because an earlier topic already built the piece you're reaching for.

Two structures, doing two different jobs, at once

The Skyline Problem is the clearest example: a sweep line (from Intervals) decides when to check the skyline's height, and a multiset (from Heap/Priority Queue's world of "track the current extreme efficiently") decides what that height currently is. Sliding Window Median pairs a sliding window with two balanced multisets standing in for the two-heap median-finder — swapped in specifically because a sliding window needs to remove an *arbitrary* falling-out value, something a heap alone can't do without extra bookkeeping. Trapping Rain Water II takes the 2D grid instinct from graph traversal and fuses it with a min-heap doing Dijkstra-style "always expand the lowest known barrier first" — turning a 1D two-pointer problem's 2D generalization into a shortest-path-flavored problem instead.

The habit to build

When a problem's requirements sound like two different earlier topics stapled together ("track the current max, but over a sliding window"; "find shortest paths, but the 'distance' is a barrier height, not a sum"), that's the signal: don't invent a new technique, combine two you already trust.

The Skyline Problem's output is exactly this outline — the tallest building "wins" at every x-coordinate. A sweep line (Intervals) decides WHEN the outline can change; a multiset tracking active heights (Heap/Priority Queue) decides WHAT the current tallest height is. Neither tool alone answers the question; together, they do.

Memoization is what separates "correct" from "finishes"

Word Break II and Longest Increasing Path in a Matrix both have a correct-looking solution that's also an exponential-time disaster without one addition: caching results keyed by whatever sub-problem repeats. Word Break II memoizes on the remaining suffix; Longest Increasing Path memoizes on the starting cell. In both cases, the *set* of distinct sub-problems is small (polynomial), but a naive recursive walk revisits the same ones over and over from different starting points — memoization is the difference between a solution that's correct in principle and one that actually returns before the heat death of the universe.

Reframe the question so a clean recurrence exists

Burst Balloons is the sharpest lesson in this topic on why the *first* framing of a DP problem isn't always the one that works. "Which balloon bursts first?" seems natural, but changes every other balloon's neighbors in a way that's hard to fold into a recurrence. "Which balloon bursts last in this range?" is the reframe that unlocks it — because a range's last-burst balloon is guaranteed to still have exactly the range's own boundary values as its neighbors, regardless of what order everything else inside the range was burst in. Recognizing when a DP is stuck because of the framing, not the technique, is itself an advanced-synthesis skill.

Deriving structure from unusual sources

Alien Dictionary and Number of Islands II both build a familiar structure (a graph; a union-find forest) from data that doesn't look like one at first. Alien Dictionary turns a sorted word list into a directed graph by comparing adjacent words character-by-character — the *graph itself* has to be derived before topological sorting (a pattern from Graphs) can even start. Number of Islands II applies union-find *online*, one addition at a time, rather than all at once on a fixed graph — a reminder that union-find's real strength is answering "are these connected right now" incrementally, not just as a one-shot batch computation.

Common mistakes

  • Reaching for a brand-new technique when two familiar ones combine — nearly every problem in this topic is a combination, not an invention; look for which two earlier topics' tools apply before assuming neither does.
  • Skipping memoization because a recursive solution "looks" polynomial — Word Break II's classic unsegmentable-input trap and Longest Increasing Path's overlapping-suffix problem both look deceptively simple until you trace how many times the same sub-problem gets re-solved.
  • Getting stuck on a DP's first framing — Burst Balloons is unsolvable with a naive "burst order left to right" recurrence; the fix is reframing around what's burst *last*, not first.
  • Forgetting event-order tiebreaks in a sweep line — The Skyline Problem's shared-x-coordinate ordering (start events before end events, tallest starts and shortest ends first) is what prevents a spurious dip; getting this backwards produces a subtly wrong skyline that only shows up on inputs with touching buildings.
  • Trying to remove an arbitrary value from a plain heap — Sliding Window Median's whole design (two multisets instead of two heaps) exists because heaps only expose their top element for removal; anything else needs either lazy deletion or a different structure entirely.

Takeaways

  • Almost every problem in this topic is a combination of two earlier topics' tools, not a new idea — identify which two before reaching for something unfamiliar.
  • Memoization on the right sub-problem key is what separates a correct-looking recursive solution from one that actually finishes in time.
  • When a DP recurrence won't close, check whether reframing "what happens first" as "what happens last" (or vice versa) fixes it.
  • A graph, a union-find forest, or any other familiar structure can be derived from data that doesn't look like it at first — the derivation step is often the real problem, not the traversal afterward.

Try it: two structures, two jobs, one sweep

The Skyline Problem — a sweep line deciding when to check, a multiset deciding what the current height is.

Live

Loading starter code…

Try it: reframing a DP recurrence

Burst Balloons — work out why "last burst" unlocks a recurrence that "first burst" can't before checking the hint.

Live

Loading starter code…

Try it: memoization as the difference between correct and finishing

Word Break II — the classic unsegmentable-input case that separates a memoized solution from an exponential one.

Live

Loading starter code…

You've reached the end of the roadmap

That's 3 of the 12 problems in this final topic — and the last of 20 topics in the Algorithms track. Alien Dictionary is worth doing next if graphs-from-unusual-sources clicked with you. See the full Advanced Synthesis set →

Checkpoint · Advanced Synthesis

5 questions · pass at 70%

Q01
The Skyline Problem processes building-start and building-end events sorted by x-coordinate, but at a SHARED x-coordinate, it specifically processes start events (tallest first) before end events (shortest first). Why does this specific tiebreak matter?
WhyIf an end event (which REMOVES a height from the active set) were processed before a start event (which ADDS one) at the same x, the algorithm would briefly compute the active maximum with one fewer building than actually exists at that x, potentially recording an incorrect, transient dip in the skyline. Processing start events first (tallest first) and end events last (shortest first) at a shared x avoids ever computing that incorrect intermediate state.
Q02
Word Break II memoizes its recursive results keyed by the remaining SUFFIX of the string. Why is this specifically what makes the difference between exponential and polynomial time?
WhyThere are only O(n) distinct suffixes of a string of length n, but a naive recursive exploration can reach the SAME suffix through exponentially many different paths (different choices of how earlier prefixes were split). Memoizing on the suffix means each of the O(n) distinct suffixes is fully resolved exactly once; every other path that reaches an already-solved suffix reuses the cached answer instead of re-deriving it, which is what collapses the exponential blowup down to work proportional to the number of distinct suffixes.
Q03
Burst Balloons only becomes solvable as a clean DP once you reframe the recurrence around 'which balloon bursts LAST in this range' instead of 'which balloon bursts FIRST'. What specifically breaks about the 'bursts first' framing?
WhyFixing the first-burst balloon tells you its OWN coin value at that moment, but doesn't pin down anything about the neighbor relationships for the remaining bursts in the range -- those depend on whatever order you choose next, which is exactly the uncertainty a clean recurrence can't tolerate. Fixing the LAST-burst balloon in a range sidesteps this entirely: by the time it's the only one left in that range, its neighbors are necessarily the range's own boundaries (i and j), no matter what order everything else was burst in -- which is precisely what makes dp[i][j] = max over k of dp[i][k] + dp[k][j] + val[i]*val[k]*val[j] a valid, well-defined recurrence.
Q04
Sliding Window Median uses two balanced MULTISETS rather than the two-HEAP approach from the earlier Find Median From Data Stream problem. What specific limitation of heaps makes multisets the better fit here?
WhyFind Median From Data Stream only ever ADDS values, so a heap's O(log n) 'remove the top' operation is all that's ever needed. Sliding Window Median needs to REMOVE a specific, arbitrary value every time the window slides (whatever value is falling out) -- something a plain heap doesn't support efficiently (finding and removing an arbitrary element in a heap is O(n), or requires extra lazy-deletion bookkeeping). A multiset supports removing any specific value directly in O(log k), which is exactly the operation this problem actually needs.
Q05
Alien Dictionary derives its graph's edges by comparing each pair of ADJACENT words in the given list and finding their first differing character. Why does the algorithm need to explicitly reject the case where a longer word appears immediately before its own prefix (like "abc" before "ab")?
WhyComparing "abc" and "ab" character by character finds no difference within the length of the shorter word "ab" -- there's no character-level constraint to derive. But under any valid alphabet ordering, a strict prefix must sort before the longer word it's a prefix of (the same rule as ordinary dictionary order). Seeing "abc" appear before "ab" directly violates that, regardless of how the alphabet's characters are ordered -- it's not a graph-cycle problem, it's an unfixable structural contradiction that has to be checked for explicitly.

Finished Advanced Synthesis?

Pass the quiz to complete it automatically.