7 routes42 sections324 units

Unit 5.2 · about 3 h

120 / 324

Memoization, tabulation and dependency order

Memoized recursion dies near depth 1000 in CPython. Tabulation with an explicit order is the form that survives production-sized inputs.

  • implement

You can now

  • Implement memoized and tabulated forms of one recurrence and show they compute the same values.
  • Read dependencies off a recurrence and state the evaluation order before writing the loop.
  • Predict when memoized recursion hits the Python recursion limit and switch to tabulation.

Covers

  • Dependency order and topological evaluation
  • Memoized recursion and state identity
  • Bottom-up tabulation and iteration order

Study, in this order

3 steps

  1. Fibonacci from naive recursion to iteration
    Algorithms - dynamic programming

    Section 3.1 (pp. 97-102): RecFibo, the \(T(n) = 2F(n+1) - 1\) call-count argument, MemFibo, IterFibo and IterFibo2

    Depth · Skip Section 3.2, the matrix-squaring speedup (p. 103), until the limits unit.

  2. The four-step conversion to a table
    DSA Handbook - dynamic programming

    The four-step conversion: dependency DAG, topological order, loop, array; Tracing the table fill on \(n = 8\)

  3. The default 1000-frame limit
    Python sys: recursion limit

    sys.getrecursionlimit and sys.setrecursionlimit: the limit guards the C stack, and the highest safe value is platform-dependent. Check the current value with sys.getrecursionlimit() (1000 on CPython 3.13).

Focus on

  • Memoization visits states lazily in recursion order; tabulation visits them eagerly in an order you choose. Both compute the same values.
  • The dependency DAG must be acyclic. For \(\operatorname{fib}(i)\) the edges run to smaller indices, so increasing \(i\) is a valid topological order.
  • A Python frame per index means depth-\(n\) recursion needs a limit above \(n\). Set it once at module top level, never per function.
  • State count times per-state work gives total time: \(O(n)\) states at \(O(1)\) each is \(O(n)\) for Fibonacci.

Reproduce closed-book

Closed-book in Python 3.13, write memoized and tabulated fib. Both give \(\operatorname{fib}(25) = 75025\). At the default limit of 1000, \(\operatorname{fib}(2500)\) raises RecursionError; with the limit raised once to 10000 the memoized form returns a 523-digit integer, and the tabulated form returns the same digits. Assert the two results are equal.

Traps

  • Reusing one global memo across calls for state that is not absolute. Stale entries from the previous call return wrong answers; build a fresh memo per call.
  • Returning a mutable object from a memoized function and letting the caller mutate it. Later cache hits return the mutated object.
  • Copying a top-down recurrence into a bottom-up loop without flipping the direction. A left-to-right loop reading \(\text{dp}[i+1]\) reads uninitialized cells.

Practice

LeetCode 509 - Fibonacci Number

Implement memoized and tabulated forms; check \(n = 2, 3, 4\) (answers 1, 2, 3), then submit.

Compare both forms on \(n = 30\). After submitting, use the DSA Handbook dp-recursion-to-memo ladder as the reference.

LeetCode 1137 - N-th Tribonacci Number

Extend the window to three predecessors; check \(n = 4\) (answer 4) and \(n = 25\) (answer 1389537), then submit.

Carry three rolling values in the tabulated form. After submitting, compare with the DSA Handbook fixed look-back section.

Self-test

  1. \(\operatorname{fib}(2500)\) under the default limit: what happens and why?

  2. When is tabulation better than memoization if both are \(O(n)\)?

  3. Your bottom-up loop reads \(\text{dp}[i+1]\) left to right and returns garbage. What went wrong?

  4. Why must a memoized function be pure?

Completion criterion

Stop when

Both forms agree on \(\operatorname{fib}(25) = 75025\) from a blank file, and you can state the order and the limit behavior without notes.

Mark passed, then open 5.3 Only mark this when you can do it without notes.

Leads to

Comes after

Resources for this unit

  • DSA Handbook - dynamic programming
    Handbook Academyprimarycourse
    Study Part 9 in order from state and recurrence through sequence, grid, tree and bitmask families. For every example, close the page and reconstruct the state, transition and evaluation order.
  • Algorithms - dynamic programming
    Jeff Ericksonrequiredtheory
    Use the dynamic-programming chapter to derive states and recurrences from first principles and to separate DP from greedy reasoning and shortest paths.
  • Python sys: recursion limit
    Python Software Foundationreferencereference
    Read sys.getrecursionlimit and sys.setrecursionlimit: the limit guards the C stack and its safe maximum is platform-dependent. Check the default with getrecursionlimit (1000 on CPython 3.13), raise it once for memoized DP, or switch to tabulation for deep inputs.

Also in this section

  • AlgoMaster DSA - dynamic programming slice
    AlgoMasterrequiredpractice
    Attempt Coin Change, Longest Common Subsequence and House Robber III cold. Write the state, transition, base case and evaluation order first; compare against brute force on small inputs and reconstruct a witness when available.
  • Hypothesis - exhaustive and differential DP tests
    Hypothesissupportpractice
    Generate small valid instances, compare memoized, tabulated and exhaustive results, and retain shrunk failures for wrong state, base case, order and compression defects.
  • NeetCode - unseen mixed problems
    NeetCodeoptionalassessment
    Use two tag-hidden mixed problems as the final transfer test. One must require rejecting a tempting greedy or insufficient-state solution with a counterexample.
  • Erickson lecture note D - Advanced Dynamic Programming
    Jeff Ericksonreferencetheory
    Read Section D.1 (Saving Space: Divide and Conquer) for the Hirschberg Half-table split that recovers an optimal edit sequence in \(O(m + n)\) space.
  • Erickson lecture note J - Approximation Algorithms
    Jeff Ericksonreferencetheory
    Read Section J.1 (Load Balancing) for the Partition reduction that makes exact scheduling NP-hard, the GreedyLoadBalance heuristic, and Theorem J.1 with its factor-2 proof.

Quick find

Search Michi

Type to search every route, section, unit, topic and resource.

Enter opens the first result Esc closes

Reference

Keyboard shortcuts

n
Continue to the first unit not passed
j / k
Next / previous unit
1 2 3
Toggle learned, practised, passed
/
Open search
?
Show this help
Esc
Close open panels