"Memoization is the gentlest way into dynamic programming: write the obvious recursion, then add a cache. Often it's a one-line change that turns an exponential disaster into a linear-time solution."
Recursion Plus a Cache
Memoization is top-down DP: you write the natural recursive solution — the one that directly mirrors the problem — and add a cache that remembers each subproblem's answer the first time it's computed. Every later request for that same subproblem is an instant lookup instead of a recomputed subtree. It's called top-down because you start at the big problem and recurse down toward the base cases, caching results as the recursion unwinds. The beauty: you don't have to redesign anything — you take a correct (but slow) recursion and make it fast by remembering.
The Cache Key Is the State
A cache key must contain the complete immutable state that determines the answer. Function arguments are suitable only when the function is effectively pure and does not hide relevant mutable or external state. @functools.cache automates storage for hashable arguments; it does not prove that the chosen state is complete.
The Trade-Offs
Memoization's strengths: it's the easiest DP to write (just cache a recursion you already trust), and it's lazy — it only ever computes the subproblems actually needed to answer your query, skipping unreachable states a bottom-up table would waste time filling. Its weaknesses: it rides the call stack, so very deep state chains can hit the recursion limit (the Recursion-track caution), and the cache carries some memory and lookup overhead. For most problems, memoization is the right first move — reach for the bottom-up table (next lesson) only when depth or space forces it.
Pippa's Confession
@cache above my existing recursive function and it went from timing out to instant. I felt slightly cheated — that's dynamic programming? But that's the honest truth of top-down DP: if your recursion is correct, memoization is often a single decorator away. The hard part was never the caching; it was writing the right recurrence, which I'd already done.