Dynamic
Programming-
1
ANALYSIS OF ALGORITHMS
Intro
Dynamic Programming (DP) is a method for solving complex problems by breaking
them down into simpler subproblems, solving each subproblem only once, and storing
its solution. This approach avoids redundant computations by reusing the results of
previously solved subproblems.
Dynamic Programming is particularly effective for optimization problems and is
characterized by two key principles:
1.Overlapping Subproblems: The problem can be divided into smaller subproblems
that are reused multiple times in the overall computation.
2.Optimal Substructure: The solution to the overall problem can be constructed
efficiently from the solutions of its subproblems.
Approaches
DP typically involves two approaches:
•Top-Down (Memoization): Solve the problem
recursively, storing solutions to subproblems to avoid
redundant calculations.
•Bottom-Up (Tabulation): Solve the problem iteratively
by solving smaller subproblems first and building up to the
solution of the main problem.
Fibonacci number
def fibonacci(n):
if n <= 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2)
Time Complexity
The time complexity of the recursive Fibonacci algorithm without using Dynamic Programming is
O(2ⁿ).
Top Down Approach in DP
int fibonacci_topdown(int n, unordered_map<int, int>& memo)
{
if (memo.find(n) != memo.end()) // Check if already
computed
return memo[n];
if (n <= 0) // Base case
return 0;
if (n == 1) // Base case
return 1;
// Compute and store the result
memo[n] = fibonacci_topdown(n - 1, memo) +
fibonacci_topdown(n - 2, memo);
Bottom Up
int fibonacci_bottomup(int n) {
if (n <= 0) return 0; // Base case
if (n == 1) return 1; // Base case
int prev1 = 0, prev2 = 1, current = 0;
for (int i = 2; i <= n; i++) {
current = prev1 + prev2; // Calculate the current Fibonacci number
prev1 = prev2; // Update prev1 to the previous Fibonacci number
prev2 = current; // Update prev2 to the current Fibonacci number
}
return current;
}