Programming/Dynamic
Properties
- tags
- Programming, Algorithm, Diataxis/Reference, Algorithm
- alias
- Dynamic Programming
Dynamic Programming Reference
Overview
- Dynamic programming is an algorithmic paradigm that solves complex problems by breaking them down into simpler subproblems
- It stores the results of subproblems to avoid redundant computations, trading space for time
- The approach is particularly effective for optimization problems with overlapping subproblems and optimal substructure
Core Principles
Optimal Substructure
- An optimal solution to a problem contains optimal solutions to its subproblems
- Example: In shortest path problems, the optimal path from A to C contains the optimal path from A to B and B to C
- Mathematical formulation: If
Displayed: S^*is optimal for problemDisplayed: P, then any sub-solutionDisplayed: S^*_iis optimal for subproblemDisplayed: P_i
Overlapping Subproblems
- The same subproblems are solved multiple times during the computation
- Dynamic programming stores these results to avoid recomputation
- Example: Fibonacci sequence calculation reuses
Displayed: F(n-1)andDisplayed: F(n-2)multiple times - Without DP:
Displayed: F(5)computesDisplayed: F(3)twice,Displayed: F(2)three times,Displayed: F(1)five times
Implementation Approaches
Top-Down (Memoization)
- Recursive approach with caching of computed results
- Starts from the original problem and works down to base cases
- Uses a memo table to store intermediate results
- Example: Recursive Fibonacci with memoization
def fib_memo(n, memo={}): if n in memo: return memo[n] if n <= 1: return n memo[n] = fib_memo(n-1, memo) + fib_memo(n-2, memo) return memo[n]
Bottom-Up (Tabulation)
- Iterative approach that builds solutions from base cases up
- Fills a table systematically, ensuring all dependencies are computed first
- Generally more space-efficient than top-down approaches
- Example: Iterative Fibonacci using an array
def fib_tab(n): if n <= 1: return n dp = [0] * (n + 1) dp[1] = 1 for i in range(2, n + 1): dp[i] = dp[i-1] + dp[i-2] return dp[n]
Classic Problems
Fibonacci Sequence
- Problem: Calculate
Displayed: F(n)whereDisplayed: F(n) = F(n-1) + F(n-2),Displayed: F(0) = 0,Displayed: F(1) = 1 - Time complexity:
Displayed: O(n)with DP vsDisplayed: O(2^n)with naive recursion - Space complexity:
Displayed: O(1)with bottom-up,Displayed: O(n)with top-down - Mathematical recurrence:
Displayed: F(n) = F(n-1) + F(n-2)forDisplayed: n \geq 2
- Problem: Calculate
Longest Common Subsequence (LCS)
Knapsack Problem
Edit Distance
Matrix Chain Multiplication
- Problem: Find optimal parenthesization to minimize scalar multiplications
- Time complexity:
Displayed: O(n^3)for the DP solution - Space complexity:
Displayed: O(n^2)for the memoization table - Recurrence:
Displayed: dp[i][j] = \min(dp[i][k] + dp[k+1][j] + p[i-1] \times p[k] \times p[j])forDisplayed: i \leq k < j
Algorithmic Patterns
- 1D state (Fibonacci, climbing stairs)
- 2D state (LCS, edit distance)
- 3D state (complex constraints)
Space Optimization Techniques
Rolling Arrays
- Use only the last few rows/columns of the DP table
- Reduces space complexity from
Displayed: O(n^2)toDisplayed: O(n)in many cases - Example: LCS can be solved with
Displayed: O(\min(m,n))space - Implementation pattern:
# Instead of dp[n][m], use dp[2][m] or dp[m] prev = [0] * (m + 1) curr = [0] * (m + 1) for i in range(1, n + 1): for j in range(1, m + 1): # compute curr[j] using prev prev, curr = curr, prev # swap arrays
State Compression
Time Complexity Analysis
General Formula
Common Patterns
- 1D DP:
Displayed: O(n)states,Displayed: O(1)transitions →Displayed: O(n)total - 2D DP:
Displayed: O(n^2)states,Displayed: O(1)transitions →Displayed: O(n^2)total - Tree DP:
Displayed: O(n)states,Displayed: O(\text{degree})transitions →Displayed: O(n \times \text{degree})total - State space analysis:
Displayed: |S| = \prod(\text{dimensions})
- 1D DP:
Problem Recognition
Mathematical Foundations
Bellman's Principle of Optimality
- "An optimal policy has the property that whatever the initial state and initial decision are, the remaining decisions must constitute an optimal policy with regard to the state resulting from the first decision."
- Mathematical form: If
Displayed: \pi^*is optimal, thenDisplayed: \pi^*_tis optimal for subproblem starting at timeDisplayed: t
Recurrence Relations
Related References