Dynamic Programming Pattern
Dynamic Programming (DP) is a method for solving complex problems by breaking them down into simpler subproblems. It stores the results of subproblems to avoid recomputing them, making it highly efficient for problems with overlapping subproblems and optimal substructure.
When to Use This Pattern
- Problems with overlapping subproblems
- Problems with optimal substructure (optimal solution contains optimal solutions to subproblems)
- Optimization problems (maximize or minimize something)
- Counting problems (how many ways to...)
- Problems that can be solved recursively but are inefficient
Key Concepts
1. Overlapping Subproblems
The problem can be broken down into subproblems which are reused several times. For example, in Fibonacci, F(5) = F(4) + F(3), and F(4) = F(3) + F(2), so F(3) is computed multiple times.
2. Optimal Substructure
An optimal solution to the problem contains optimal solutions to subproblems. For example, the shortest path from A to C through B is the shortest path from A to B plus the shortest path from B to C.
3. Two Approaches
- Top-Down (Memoization): Start with the main problem and recursively solve subproblems, storing results in a memo table.
- Bottom-Up (Tabulation): Start with the smallest subproblems and build up to the main problem using a table.
Visual Representation - Fibonacci DP
Dynamic Programming - Fibonacci Sequence Comparison
Key Insight: DP stores results of subproblems to avoid recomputation. This transforms exponential O(2^n) time to linear O(n) time, making it feasible to compute large Fibonacci numbers.
Common DP Patterns
- Fibonacci Numbers: F(n) = F(n-1) + F(n-2)
- 0/1 Knapsack: Choose items with weight and value constraints
- Longest Common Subsequence (LCS): Find longest common subsequence between two strings
- Longest Increasing Subsequence (LIS): Find longest increasing subsequence
- Subset Sum: Check if a subset sums to a target