Dynamic Programming
5.1 Principles
Dynamic programming (DP) solves problems by:
- Overlapping subproblems: The same subproblems are solved repeatedly.
- Optimal substructure: The optimal solution contains optimal solutions to subproblems.
Approaches:
- Top-down (memoisation): Recursive with caching.
- Bottom-up (tabulation): Fill a table iteratively from small subproblems to large.
5.2 Memoisation vs. Tabulation
| Aspect | Memoisation (Top-Down) | Tabulation (Bottom-Up) |
|---|---|---|
| Approach | Recursive with cache | Iterative table fill |
| Order | Natural recursion order | Dependency order |
| Space | stack + table | table only |
| Overhead | Function call overhead | Minimal |
| Subproblems | Computes only needed | Computes all |
| Best for | When not all subproblems needed | When all needed |
When to use which:
- Use memoisation when the subproblem space is sparse (not all subproblems are needed).
- Use tabulation when most subproblems are needed (avoids recursion overhead and stack overflow).
- Both achieve the same asymptotic time complexity.
5.3 Optimal Substructure Proof Technique
To prove that a problem has optimal substructure:
- Show that an optimal solution to the problem includes an optimal solution to a subproblem.
- Proved by contradiction: if the optimal solution contained a suboptimal sub-solution, replacing it with an optimal one would improve the overall solution.
Example (Shortest Path). If is a shortest path from to and is an intermediate vertex on Then the subpath of from to is a shortest path from to .
Proof. If not, there exists a shorter path from to . Then concatenated with the subpath of from to would be shorter than Contradicting that is a shortest path.
:::caution Common Pitfall Not all problems have optimal substructure. For example, the longest simple path problem does not: the longest simple path from to may not contain the longest simple path from to an intermediate vertex Because the subpath might share vertices with the rest of the path, creating a non-simple path.
5.4 Common Patterns
1D DP. depends on for . Example: Fibonacci, longest increasing subsequence.
2D DP. depends on for in some set. Example: edit distance, Matrix chain multiplication, longest common subsequence.
Interval DP. depends on where . Example: Optimal BST, matrix chain multiplication.
5.5 Worked Example: 0/1 Knapsack
Problem. Given items with weights and values And a knapsack of capacity Maximise the total value without exceeding the capacity.
Recurrence:
Time: . Space: (can be reduced to with 1D array).
Proof of correctness. For each item Either we don’t include it (value ) or we include it (value ). The optimal choice is the maximum. The base cases are correct.
Worked Example: 0/1 Knapsack
Items: Capacity .
Building the DP table (items as rows, capacities 0-7 as columns):
c: 0 1 2 3 4 5 6 7i=0: 0 0 0 0 0 0 0 0i=1: 0 1 1 1 1 1 1 1i=2: 0 1 1 4 5 5 5 5i=3: 0 1 1 4 5 6 6 9i=4: 0 1 1 4 5 7 8 9Maximum value: (items 2 and 4: , — let me recalculate).
Correct: items 2 and 3 (, ), or items 1, 2, 4 (Not valid). Items 1, 3 (, ), items 2, 4 (). Optimal: items 2 and 3 (, ).
5.6 Worked Example: Edit Distance (Levenshtein Distance)
Problem. Given strings of length and of length Find the minimum number of insertions, deletions, and substitutions to transform into .
Recurrence:
Where the three cases in the minimum are: delete from Insert into Substitute in .
Time: . Space: (can be reduced to ).
Worked Example: Edit Distance
Compute the edit distance between “kitten” and “sitting”.
Building the DP table:
"" s i t t i n g"" 0 1 2 3 4 5 6 7k 1 1 2 3 4 5 6 7i 2 2 1 2 3 4 5 6t 3 3 2 1 2 3 4 5t 4 4 3 2 1 2 3 4e 5 5 4 3 2 2 3 4n 6 6 5 4 3 3 2 3Edit distance: .
Transform: kitten → sitten (substitute k→s) → sittin (substitute e→i) → sitting (insert g).
5.7 Worked Example: Matrix Chain Multiplication
Problem. Given matrices where has dimensions Find the parenthesisation that minimises the total number of scalar multiplications.
Recurrence:
Time: . Space: .
Proof of correctness. The optimal parenthesisation of splits at some position : . The cost is the cost of the left subproduct plus the cost of the right subproduct plus the cost of multiplying the resulting matrices ( scalar multiplications). The optimal minimises this total.
Worked Example: Matrix Chain Multiplication
Matrices: (), (), (). Dimensions: .
.
. Split at : .
. Split at : .
: Try : . Try : .
Minimum: Split at : .
5.8 Worked Example: Longest Common Subsequence
Problem. Given sequences and Find the LCS.
Recurrence:
Time: . Space: (can be reduced to for the length only).
Proof of correctness. If Any LCS of and must include So . If The LCS either Excludes or excludes Giving the max of the two subproblems.
5.9 Worked Example: Coin Change
Problem. Given coin denominations and a target amount Find the minimum number of coins needed.
Recurrence:
Time: . Space: .
Proof of correctness. To make change for amount The last coin used must be some . The remaining amount is And the optimal solution for uses coins. Taking the minimum over all valid gives the optimal solution.
Worked Example: Coin Change
Denominations: . Target: .
Bottom-up computation:
- (use pennies)
- (use a nickel)
- (use a dime)
- …
- (use a quarter)
- (use two quarters)
Working backwards: .
Solution: 2 quarters + 1 dime + 3 pennies = . 6 coins.
5.10 Worked Example: Longest Increasing Subsequence
Problem. Given a sequence Find the length of the longest strictly increasing subsequence (not necessarily contiguous).
Recurrence: With if no such exists.
Time: . Space: .
Worked Example: Longest Increasing Subsequence
Find the LIS of .
(just 10) (10, 22) (just 9) (10, 22, 33) (10, 21) (10, 22, 33, 50) (10, 21, 41) (10, 22, 33, 50, 60) (10, 22, 33, 50, 60, 80)
LIS length: 6.
Patience sorting approach (): Maintain piles. For each card, place on the leftmost pile whose top card is the current card, or start a new pile on the right if no such pile exists. The number of piles equals the LIS length.
:::