Tabulation (bottom-up DP) — iterative
WHAT is tabulation?
WHY does it work? A DP problem has optimal substructure (answer built from sub-answers) and overlapping subproblems (same sub-answers needed repeatedly). If we compute each subproblem once in an order where its dependencies are already done, we never recompute and never recurse.
HOW to build any tabulation (the recipe)
Deriving the canonical example: Fibonacci
We want where .
Step 1 — State. dp[i] = the -th Fibonacci number.
Step 2 — Recurrence. By definition .
Why this step? Each Fibonacci number is literally the sum of the two before it — that IS the optimal substructure.
Step 3 — Base cases. dp[0]=0, dp[1]=1.
Step 4 — Order. Increasing : when we compute dp[i], both dp[i-1] and dp[i-2] already exist. ✅
Step 5 — Answer. dp[n].
def fib(n):
if n < 2: return n
dp = [0]*(n+1)
dp[1] = 1
for i in range(2, n+1):
dp[i] = dp[i-1] + dp[i-2] # read smaller, already filled
return dp[n]
Worked example 2 — Climbing Stairs (counting paths)
You climb stairs, taking 1 or 2 steps at a time. How many distinct ways?
State. dp[i] = number of ways to reach step .
Recurrence. To land on step , your last move was a 1-step (from ) or a 2-step (from ):
Why this step? The set of ways splits cleanly by the last action; the two cases are disjoint, so we add them.
Base. dp[0]=1 (one way: stand still), dp[1]=1.
Answer. dp[n].
def climb(n):
dp = [0]*(n+1)
dp[0] = dp[1] = 1
for i in range(2, n+1):
dp[i] = dp[i-1] + dp[i-2]
return dp[n]Same shape as Fibonacci — many DP problems share skeletons.
Worked example 3 — 0/1 Knapsack (2D table)
Items with weights , values , capacity . Maximise value, each item used at most once.
State. dp[i][c] = best value using the first items with capacity .
Recurrence. For item (1-indexed, weight , value ):
Why this step? Every item is either in or out — that binary choice is the substructure. If we take it, capacity shrinks by and value grows by , leaving a smaller subproblem dp[i-1][c-w_i].
Base. dp[0][c]=0 (no items → no value).
Order. Increasing (rows), any order on , because every read uses row which is fully done.
def knapsack(w, v, W):
n = len(w)
dp = [[0]*(W+1) for _ in range(n+1)]
for i in range(1, n+1):
for c in range(W+1):
dp[i][c] = dp[i-1][c] # skip item i
if w[i-1] <= c:
dp[i][c] = max(dp[i][c],
v[i-1] + dp[i-1][c-w[i-1]]) # take it
return dp[n][W]Common mistakes (steel-manned)
Recall Feynman: explain to a 12-year-old
Imagine building a LEGO tower. You can't put the 5th brick before the 4th. So you start at the bottom: place brick 1, then 2 using brick 1, then 3 using brick 2… Each brick remembers what's below it, so you never rebuild anything. Tabulation is exactly this: you write down small answers in boxes, then stack bigger answers on top of them — one loop, no magic, no going back.
Active recall
Tabulation is which direction of DP?
Why does tabulation avoid recursion overhead?
What two properties must a problem have for DP/tabulation?
In what order must you fill the table?
Fibonacci tabulation recurrence and base cases?
Climbing stairs recurrence — why is it a sum not a max?
0/1 knapsack take-vs-skip recurrence?
In space-optimized 1D knapsack, why loop capacity high→low?
What is the difference between memoization and tabulation?
Where does the final answer usually sit in a tabulation table?
Connections
- Memoization (top-down DP) — the recursive dual of this note
- Dynamic Programming — parent paradigm
- Optimal Substructure and Overlapping Subproblems — prerequisites
- 0-1 Knapsack, Longest Common Subsequence, Coin Change — classic tabulation problems
- Space Optimization in DP — rolling arrays from 2D tables
- Recurrence Relations — the math under the recurrence step
Concept Map
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Tabulation ka matlab hai DP ko bottom-up solve karna — sabse chhote subproblems pehle solve karo, unke answers ek table (array) mein store karo, aur phir un chhote answers ko use karke bade answers banao. Sab kuch loop se hota hai, koi recursion nahi. Jaise ladder pe chadhte time aap rung 1, phir 2, phir 3 banate ho — rung 10 tab tak nahi ban sakta jab tak neeche wale ready na hon.
Ye kaam isliye karta hai kyunki DP problems mein optimal substructure (bada answer chhote answers se banta hai) aur overlapping subproblems (same chhota answer baar-baar chahiye) hota hai. Agar hum sahi order mein chalein — jahan har cell ke dependencies pehle se filled ho — to har subproblem sirf ek baar compute hota hai. Isiliye Fibonacci mein hum i ko 2 se n tak badhate hain, kabhi ghatate nahi, taki dp[i-1] aur dp[i-2] already ready milen.
Recipe yaad rakho: State (dp[i] ka matlab kya), Base case (sabse chhota answer direct likho), Order (chhota se bada loop), aur Answer (kaunse cell mein final result). Climbing stairs aur Fibonacci ka skeleton same hai — dp[i]=dp[i-1]+dp[i-2] — bas counting mein hum add karte hain, optimisation mein max lete hain. Knapsack 2D table use karta hai jahan har item ko lo ya chhodo ka choice hota hai.
Sabse common galti: log recursion ki tarah bade se chhote loop chala dete hain — galat! Tabulation mein hamesha dependencies pehle fill karo, yani usually chhota se bada. Aur base cases kabhi mat bhoolna, warna pura table 0 reh jayega ya crash ho jayega.