Dynamic Programming
2D DP
Master 2D Dynamic Programming: unique grid paths, 0/1 Knapsack capacity states, and Longest Common Subsequence using both Top-Down and Bottom-Up designs.
Last Updated: August 2, 2026
•
20 min read
1. Introduction
What is 2D DP?
2D DP represents dynamic programming problems where the subproblem states are modeled using two variables, e.g.dp[i][j] represents the optimal solution at grid coordinate (i, j), or the optimal choice considering prefix lengths i of string s1 and j of string s2.
Why study it?
Many optimizations involve relations between two dimensions (like backpack capacity vs items, or string A vs string B alignment). Mastering 2D state transition tables is crucial for advanced pathfinding and string matching interviews.2. Mental Models
0/1 Knapsack: Cap vs Item Decisions
Imagine packing a backpack with items:i with weight w and value v, at capacity limit c:i: Remaining capacity decreases to c - w. Your total value is v + value_with_remaining(i - 1, c - w).
- Skip item i: Capacity stays at c. Total value is identical to value_with_remaining(i - 1, c).
dp[i][c] = max(dp[i-1][c], dp[i-1][c - w] + v).LCS: String Grid Alignments
Imagine matching characters between two words"abcde" and "ace" on a grid:
s1[i] == s2[j]), you extend the matching sequence: dp[i][j] = 1 + dp[i-1][j-1].dp[i][j] = max(dp[i-1][j], dp[i][j-1]).3. Core Algorithms & Implementations
1. Unique Paths (LeetCode 62)
dp[i][j] = number of unique paths from (0, 0) to (i, j).dp[i][j] = dp[i-1][j] + dp[i][j-1].2. 0/1 Knapsack
dp[i][c] = max value using first i items with capacity c.dp[i][c] = max(dp[i-1][c], dp[i-1][c - wt[i-1]] + val[i-1]) if wt[i-1] <= c.3. Longest Common Subsequence (LeetCode 1143)
dp[i][j] = length of LCS of prefix s1[0...i-1] and s2[0...j-1].dp[i][j] = 1 + dp[i-1][j-1] if s1[i-1] == s2[j-1]
- dp[i][j] = max(dp[i-1][j], dp[i][j-1]) if s1[i-1] != s2[j-1]4. Visualizing Subproblem Pruning (LCS)
Table compilation trace of LCS between "abcde" and "ace":
dp[i][j] holds the optimal common sequence count up to that point. The final result dp[5][3] = 3 represents sequence "ace".5. Real-World Examples
6. Interview Perspective
How Interviewers Ask This Topic
Interviewers test space optimization capabilities:dp[i][j] only requires values from the previous row dp[i-1] and the current row dp[i]. Thus, we can maintain a single 1D array of size N + 1 and update it in-place.for (int w = W; w >= wt[i]; w--) in the space-optimized version?"dp[w] using values from the previous item iteration dp[w - wt[i]]. If we ran it forwards, we would overwrite values, leading to multiple uses of the same item (solving the Unbounded Knapsack problem instead of 0/1 Knapsack).Common Mistakes
Warning: 1. Forward capacity loops in Knapsack: Running the capacity loop forwards in 1D Knapsack tabulation. Always run it backwards for 0/1 Knapsack.
> 2. Wrong LCS Indexing: Referencings1[i]instead ofs1[i-1]in 1-indexed DP tables, causing off-by-one errors.
7. Summary
dp[i][j] = dp[i-1][j] + dp[i][j-1].dp[w] = max(dp[w], val[i] + dp[w - wt[i]]) (inner loop runs backwards).1 + dp[i-1][j-1]; mismatch leads to max(up, left).8. Quiz
Question 1: What is the space complexity of the space-optimized LCS algorithm?
Answer:O(\min(M, N)) space, by allocating the 1D array to match the length of the shorter string.
Question 2: What is the base case value for knapsackTopDown(i, w) when capacity w reaches 0?
Answer:0. You cannot pack any value when the remaining capacity is 0.
Question 3: If s1 = "apple" and s2 = "pear", what is their LCS length?
Answer:2 (the subsequence "pe").
Question 4: True or False: 0/1 Knapsack cannot be solved using a Top-Down Memoization approach.
Answer: False. You can solve it using recursive memoization with a cache key representing(itemIndex, remainingCapacity).
Question 5: If grid obstacles are added to Unique Paths, how does the recurrence change?
Answer: Ifgrid[i][j] == obstacle, then dp[i][j] = 0. Otherwise, the recurrence remains dp[i][j] = dp[i-1][j] + dp[i][j-1].