Bottom Up DP from Top Down DP
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Converting a top-down dynamic programming solution into a bottom-up one is mostly an exercise in understanding dependencies. A memoized recursive function already tells you which subproblems each state needs. Bottom-up DP simply computes those same states in an order where every dependency is already available. Once you see the recurrence as a dependency graph, the conversion becomes mechanical.
Start by reading the top-down state and recurrence
Suppose you have this top-down solution for the minimum number of coins needed to make a target amount:
The state is remaining. The transition says: to compute solve(remaining), you need answers for smaller amounts such as remaining - coin.
That already tells you the bottom-up order: compute from 0 upward.
Translate base cases into table initialization
Top-down base cases become initial table values in bottom-up DP.
In the example above:
- '
solve(0) = 0becomesdp[0] = 0' - impossible states start as infinity
Then you fill the table in increasing amount order, because every dp[current - coin] refers to a smaller amount that should already be computed.
That is the same recurrence, just evaluated in a loop instead of through recursion.
A reliable conversion recipe
For many problems, you can convert top-down to bottom-up with the same checklist:
- identify the DP state parameters
- write down the recurrence plainly
- find which states each state depends on
- choose a loop order where those dependencies are computed first
- translate base cases into initial table values
If the top-down state has two parameters, such as dp(i, j), the bottom-up version usually becomes a 2D table with nested loops. The challenge is deciding which dimension should go forward, backward, or both.
Dependency order is the real skill
The hardest part is not syntax. It is dependency direction.
For example:
- if
dp[i]depends ondp[i - 1], loop upward - if
dp[i]depends ondp[i + 1], loop downward - if
dp[i][j]depends ondp[i - 1][j]anddp[i][j - 1], loop forward on both axes
This is why converting DP is easier when you sketch a small dependency graph by hand. The loops then almost write themselves.
Bottom-up can enable space optimization
Once the table order is explicit, you can often see that only a small part of the table is needed at any time. That is harder to notice in top-down recursion.
For example, Fibonacci or climbing-stairs problems often depend only on the previous one or two states, so a full array can collapse to a few variables:
That kind of optimization usually appears only after you already understand the bottom-up order.
Common Pitfalls
The most common mistake is copying the recurrence correctly but choosing the wrong loop order. If dependencies are not computed yet, the table fills with wrong values very quickly.
Another issue is forgetting to translate top-down base cases into bottom-up initialization. A good recurrence with bad initial values still fails.
Developers also preserve unreachable-state logic poorly. If the top-down code used float("inf"), None, or -1 as a sentinel, the bottom-up table needs an equivalent representation.
Finally, do not convert blindly. Some problems are easier to reason about top-down first. The top-down version is often the tool that reveals the correct state space.
Summary
- Bottom-up DP is the same recurrence as top-down DP evaluated in dependency order.
- Base cases become initial table values.
- The loop order comes directly from which smaller states each state depends on.
- Converting to bottom-up often makes space optimization easier to see.
- When in doubt, sketch the dependency graph before writing loops.

