šÆ Dynamic Programming (DP) ā Comprehensive Study Guide
**Dynamic Programming (DP)** is an **optimization technique** used to solve problems by breaking them down into **overlapping subproblems** and storing results to avoid redundant calculations.
ā” Why Use Dynamic Programming?
- ā **Reduces time complexity** compared to recursion.
- š **Optimizes solutions for combinatorial problems**.
- š **Efficiently solves overlapping subproblems**.
- š **Used in AI, machine learning, and optimization algorithms**.
š Key Differences: Recursion vs Dynamic Programming
Feature | Recursion | Dynamic Programming |
---|---|---|
Approach | Solves problem by **dividing** into smaller problems | Solves problem **by storing results** of subproblems |
Time Complexity | O(2āæ) (Exponential in some cases) | O(n) or O(n²) (Optimized) |
Redundant Calculations | Yes (Overlapping subproblems) | No (Uses memoization or tabulation) |
Memory Usage | High (Recursive stack calls) | Optimized (Stores only necessary values) |
š ļø Types of Dynamic Programming Approaches
š„ 1ļøā£ **Top-Down Approach (Memoization)**
Uses **recursion + caching** to store previously computed results.
int dp[100] = { -1 };
int fibonacciMemo(int n) {
if (n <= 1) return n;
if (dp[n] != -1) return dp[n]; // Use stored result
return dp[n] = fibonacciMemo(n - 1) + fibonacciMemo(n - 2);
}
š¤ 2ļøā£ **Bottom-Up Approach (Tabulation)**
Solves subproblems **iteratively** and builds solutions step by step.
int fibonacciTabulation(int n) {
int dp[n + 1];
dp[0] = 0, dp[1] = 1;
for (int i = 2; i <= n; i++)
dp[i] = dp[i - 1] + dp[i - 2];
return dp[n];
}
ā **Memoization vs Tabulation**
- š„ **Memoization** ā Uses recursion + caching, needs more stack space.
- š¤ **Tabulation** ā Uses iteration, avoids recursion overhead.
š„ Common DP Problems & Their Solutions
š **1. Fibonacci Sequence (O(n))**
Uses **dynamic programming** to optimize recursion.
š **2. 0/1 Knapsack Problem (O(nW))**
Finds the **maximum value** we can carry in a **bag of weight W**.
int knapsack(int W, vector wt, vector val, int n) {
int dp[n+1][W+1];
for (int i = 0; i <= n; i++) {
for (int w = 0; w <= W; w++) {
if (i == 0 || w == 0)
dp[i][w] = 0;
else if (wt[i - 1] <= w)
dp[i][w] = max(val[i - 1] + dp[i - 1][w - wt[i - 1]], dp[i - 1][w]);
else
dp[i][w] = dp[i - 1][w];
}
}
return dp[n][W];
}
š **3. Longest Common Subsequence (LCS) (O(n²))**
Finds the **longest matching subsequence** between two strings.
int lcs(string X, string Y, int m, int n) {
int dp[m + 1][n + 1];
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (i == 0 || j == 0)
dp[i][j] = 0;
else if (X[i - 1] == Y[j - 1])
dp[i][j] = 1 + dp[i - 1][j - 1];
else
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
return dp[m][n];
}
š **4. Longest Increasing Subsequence (O(n²))**
Finds the **longest increasing sequence** in an array.
ā³ Time Complexity Analysis
Problem | Time Complexity | Space Complexity |
---|---|---|
Fibonacci (DP) | O(n) | O(n) or O(1) |
0/1 Knapsack | O(nW) | O(nW) |
LCS | O(n²) | O(n²) |
LIS | O(n²) | O(n) |
š Real-World Applications of DP
- š” **AI & Machine Learning** ā Predictive analytics.
- š **Data Compression** ā Image & video encoding (JPEG, MP3).
- š **Stock Market Prediction** ā Forecasting trends.
- š® **Game Development** ā AI-based decision-making.