Dynamic Programming (DP)
Solve optimization problems efficiently with the power of overlapping subproblems and optimal substructure.
What is Dynamic Programming?
Dynamic Programming (DP) is a powerful algorithmic paradigm used to solve problems by breaking them into smaller overlapping subproblems. Instead of solving the same subproblem multiple times, DP stores the results in a table (memoization or tabulation) and reuses them to optimize the overall computation.
Key Concepts in DP
- Overlapping Subproblems: The problem can be divided into subproblems that are reused multiple times.
- Optimal Substructure: The solution to the main problem can be built from the solutions to its subproblems.
DP Approaches
-
Top-Down (Memoization):
- Solve the problem recursively.
- Store the results of subproblems in a table to avoid redundant calculations.
-
Bottom-Up (Tabulation):
- Solve the problem iteratively.
- Build a solution by solving all subproblems from the smallest to the largest.
Time & Space Complexities
- Time Complexity:
O(n)
toO(n*m)
(depends on the problem and state space). - Space Complexity: Can range from
O(n)
(space-optimized DP) toO(n*m)
(when storing a table of solutions).
When to Use DP
Dynamic Programming is a great choice for problems like:
- Fibonacci numbers.
- Longest Common Subsequence (LCS).
- Knapsack problem.
- Shortest path in a graph (e.g., Floyd-Warshall, Bellman-Ford).
- Partitioning problems (e.g., Palindrome Partitioning, Subset Sum).
Code Examples
Below is an example of solving the Fibonacci sequence problem using both approaches.
# Top-Down Approach (Memoization)
def fibonacci(n, memo={}):
if n <= 1:
return n
if n not in memo:
memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo)
return memo[n]
# Bottom-Up Approach (Tabulation)
def fibonacci_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]
# Example usage
n = 10
print(f"Fibonacci({n}) using Memoization: {fibonacci(n)}")
print(f"Fibonacci({n}) using Tabulation: {fibonacci_tab(n)}")