Dynamic Programming (DP) is a technique for solving problems by breaking them down into overlapping sub-problems, solving each sub-problem once, and storing their results for future use.
Goal: Avoid redundant computations and improve efficiency.
dp[]
array).dp[]
array).⚠️ Note: Base case doesn’t always mean smallest input — it depends on the recursion logic.
0, 1, 1, 2, 3, 5, 8, 13, 21, ...
Find the nth Fibonacci number where:
F(0) = 0
,F(1) = 1
F(n) = F(n-1) + F(n-2)
forn >= 2
dp[]
array initialized with -1
dp[n]
if already computeddp[n]
int fib(int n, vector<int>& dp){
if(n <= 1) return n;
if(dp[n] != -1) return dp[n];
return dp[n] = fib(n-1, dp) + fib(n-2, dp);
}
int main() {
int n = 5;
vector<int> dp(n+1, -1);
cout << fib(n, dp);
return 0;
}
5
O(N)
O(N)
dp[]
array of size n+1
.dp[0] = 0
dp[1] = 1
i = 2
to n
and compute:
dp[i] = dp[i-1] + dp[i-2]
int main() {
int n = 5;
vector<int> dp(n+1, -1);
dp[0] = 0;
dp[1] = 1;
for(int i = 2; i <= n; i++) {
dp[i] = dp[i-1] + dp[i-2];
}
cout << dp[n];
return 0;
}
5
O(N)
O(N)
We only need the last two values at any point (dp[i-1]
, dp[i-2]
).
So instead of a full dp[]
array, we can use two variables:
int main() {
int n = 5;
int prev2 = 0;
int prev = 1;
for(int i = 2; i <= n; i++) {
int cur_i = prev2 + prev;
prev2 = prev;
prev = cur_i;
}
cout << prev;
return 0;
}
5
O(N)
O(1)