Download as pdf or txt
Download as pdf or txt
You are on page 1of 7

>> Dynamic programming is a powerful technique used in

computer science and mathematics to solve a wide range


of optimization problems.

>> It is particularly important for coding where


efficient algorithms are crucial.

>> Three fundamental approaches:


1. recursion,
2. recursion with memoization, and
3 .bottom-up dynamic programming.

Dynamic Programming
>> Dynamic programming is a problem-solving technique
that involves
>> breaking down complex problems into simpler
overlapping subproblems
>> and solving each subproblem only once,
>> storing the results to avoid redundant computation.

This approach optimizes both


>> time and space complexity
>> and is widely used for various problems such as
>> finding the shortest path,
>> maximizing profits,
>> or optimizing sequences.

Three approaches to solving a problem:

1. Recursion:
>>In this method, the problem is solved by breaking it
down into smaller subproblems, which are solved
recursively.
>> It is the simplest and most intuitive approach but
can lead to redundant computations.

2. Recursion with Memoization:


>> To address the inefficiencies of pure recursion, we
can use memoization.
>> Memoization involves storing the results of
previously solved subproblems in a data structure
(usually an array or hash table) so that we can
quickly retrieve them when needed.

3. Bottom-Up Approach (Dynamic Programming):


In this approach, we start solving the problem from
the simplest subproblems and build up the solution by
iteratively solving larger subproblems. This approach
is often more efficient than pure recursion and is
preferred when memory constraints are a concern.

Problem1: Fibonacci Sequence

Problem
Calculate the nth Fibonacci number, where F(0) = 0 and
F(1) = 1, and for n > 1, F(n) = F(n-1) + F(n-2).

----------Recursion method----------

int fibonacci(int n) {
if (n <= 1)
return n;
return
fibonacci(n - 1) + fibonacci(n - 2);
}

----------Recursion with memoization method----------

int memo[100]; // Initialize with an appropriate size


int fibonacci(int n) {
if (n <= 1)
return n;
if (memo[n] != -1)
return memo[n];
memo[n] = fibonacci(n - 1) + fibonacci(n - 2);
return memo[n];
}

-----------Bottom-Up Approach (Dynamic Programming)---


--------

int fibonacci(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];
}

Problem 2: Longest Common Subsequence

Given two strings, find the length of their longest


common subsequence.

int lcs(string s1, string s2, int m, int n) {


if (m == 0 || n == 0)
return 0;
if (s1[m - 1] == s2[n - 1])
return 1 + lcs(s1, s2, m - 1, n - 1);
else
return max(lcs(s1, s2, m, n - 1), lcs(s1, s2, m
- 1, n));
}

---------Recursion with Memoization----------

int memo[100][100]; // Initialize with appropriate


size
int lcs(string s1, string s2, int m, int n) {
if (m == 0 || n == 0)
return 0;
if (memo[m][n] != -1)
return memo[m][n];

if (s1[m - 1] == s2[n - 1])


memo[m][n] = 1 + lcs(s1, s2, m - 1, n - 1);
else
memo[m][n] = max(lcs(s1, s2, m, n - 1),
lcs(s1, s2, m - 1, n));

return memo[m][n];
}

Bottom-Up Approach (Dynamic Programming)


int lcs(string s1, string s2) {
int m = s1.length();
int n = s2.length();
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 (s1[i - 1] == s2[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];
}

Problem 3: Coin Change

Given a set of coin denominations and a target amount,


find the number of ways to make change for that
amount.

--------------Recursion--------------

int coinChange(int coins[], int n, int amount) {


if (amount == 0) return 1;
if (amount < 0 || n <= 0) return 0;
return coinChange(coins, n, amount - coins[n - 1])
+ coinChange(coins, n - 1, amount);
}
---------------Recursion with Memoization-------------
---
int memo[1000][1000]; // Initialize with appropriate
size
int coinChange(int coins[], int n, int amount) {
if (amount == 0) return 1;
if (amount < 0 || n <= 0) return 0;
if (memo[n][amount] != -1) return memo[n][amount];

memo[n][amount] = coinChange(coins, n, amount -


coins[n - 1]) + coinChange(coins, n - 1, amount);

return memo[n][amount];
}

---------------Bottom-Up Approach (Dynamic


Programming)------------
int coinChange(int coins[], int n, int amount) {
int dp[n + 1][amount + 1];

for (int i = 0; i <= n; ++i)


dp[i][0] = 1;
for (int i = 1; i <= amount; ++i)
dp[0][i] = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= amount; ++j) {
if (j < coins[i - 1]) dp[i][j] = dp[i -
1][j];
else dp[i][j] = dp[i][j - coins[i - 1]] +
dp[i - 1][j];
}
}
return dp[n][amount];
}

Problem 3: Coin Change

Given a set of coin denominations and a target amount,


find the number of ways to make change for that
amount.

4. Knapsack Problem
Given a set of items, each with a weight and a value,
determine the maximum value you can obtain by
selecting a subset of the items, such that the sum of
the weights of the selected items does not exceed a
given weight limit.
---------------Recursion-------------------

int knapsack(int weights[], int values[], int n, int


W) {
if (n == 0 || W == 0) return 0;
if (weights[n - 1] > W) return knapsack(weights,
values, n - 1, W);
return max(
values[n - 1] + knapsack(weights, values, n -
1, W - weights[n - 1]),
knapsack(weights, values, n - 1, W)
);
}

------------Recursion with Memoization----------------


----------
int memo[1000][1000]; // Initialize with appropriate
size
int knapsack(int weights[], int values[], int n, int
W) {
if (n == 0 || W == 0) return 0;
if (weights[n - 1] > W) return knapsack(weights,
values, n - 1, W);
if (memo[n][W] != -1) return memo[n][W];

memo[n][W] = max(
values[n - 1] + knapsack(weights, values, n -
1, W - weights[n - 1]),
knapsack(weights, values, n - 1, W)
);

return memo[n][W];
}

----------------Bottom-Up Approach (Dynamic


Programming)----------
int knapsack(int weights[], int values[], int n, int
W) {
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 (weights[i - 1] <= w)
dp[i][w] = max(values[i - 1] + dp[i -
1][w - weights[i - 1]], dp[i - 1][w]);
else
dp[i][w] = dp[i - 1][w];
}
}
return dp[n][W];
}

You might also like