Dynamic Programming
Telerik Academy Alpha
DSA
Table of contents
Dynamic programming
What and why?
- Dynamic programming is when you use past knowledge to make solving a future problem easier
-
Solving a complex problem
- Breaking it down into a collection of simpler subproblems
- Solve each of those subproblems just once
- Store their solutions

How it works
- How dynamic programming (DP) works?
- Approach to solve problems
- Store partial solutions of the smaller problems
- Usually they are solved bottom-up

Steps
- Steps to designing a DP algorithm:
- Characterize optimal substructure
- Recursively define the value of an optimal solution
- Compute the value bottom up
- (if needed) Construct an optimal solution
Elements of DP
- DP has the following characteristics
-
Simple sub-problems
- We break the original problem to smaller sub-problems that have the same structure
-
Optimal substructure of the problems
- The optimal solution to the problem contains within optimal solutions to its sub-problems
-
Overlapping sub-problems
- There exist some places where we solve the same sub-problem more than once
-
Simple sub-problems
DP vs Divide and Conquer
- Using Divide-and-Conquer to solve problems (that can be solved using DP) is inefficient
- Because the same common sub-problems have to be solved many times
- DP will solve each of them once and their answers are stored in a table for future use
- Technique known as memoization
Example
- In many DP problems there is a moving object with some restrictions
- For example: In how many ways you can reach from top-left corner of a grid to the bottom-right?
- You can move only right and down
- Some cells are unreachable
Fibonacci
Divide and Conquer
vs Dynamic Programming
Divide and Conquer Approach
- How can we find the n-th Fibonacci number using recursion ("divide and conquer")
Directly applying the recurrence formula:
decimal Fibonacci(int n)
{
if (n == 0) return 0;
if (n == 1) return 1;
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
Fibonacci and Memoization
- We can save the results from each function call
- Every time when we call the function we check if the value is already calculated
- This saves a lot of useless calculations!
decimal Fibonacci(int n)
{
if (memo[n] != 0) return memo[n];
if (n == 0) return 0;
if (n == 1) return 1;
memo[n] = Fibonacci(n - 1) + Fibonacci(n - 2);
return memo[n];
}

Fibonacci and DP
- How to find the n-th Fibonacci number using the dynamic programming approach?
- We can start solving the Fibonacci problem from bottom-up calculating partial solutions
- We know the answer for the 0-th and the 1-st number of the Fibonacci sequence
Fibonacci and DP
- How to find the n-th Fibonacci number using the dynamic programming approach?
- We can start solving the Fibonacci problem from bottom-up calculating partial solutions
- We know the answer for the 0-th and the 1-st number of the Fibonacci sequence
We know the formula to calculate each of the next numbers Fi=Fi−1+Fi−2
Compare Fibonacci Solutions
-
Recursive solution
- Complexity: ~O(φn) = O(1.618n)
-
DP or memoization solution
- Complexity: ~O(n)
- Dynamic programming solutions is way faster than the recursive solution
- If we want to find the 36th Fibonacci number:
- Dynamic programming solution takes ~36 steps
- Recursive solution takes ~48 315 633 steps
- If we want to find the 36th Fibonacci number:
Subset Sum
Subset sum
- Given a set of integers, is there a non-empty subset whose sum is zero?
- Given a set of integers and an integer S, does any non-empty subset sum to S?
- Given a set of integers, find all possible sums
- Can you equally separate the value of coins?
Subset sum
- Solving the subset sum problem:
- numbers = {3,5,−1,4,2}, sum=6
- start with possible = {0}
- Step 1: obtain all possible sums of {3}
- possible = {0}∪{0+3}={0,3}
- Step 2: obtain all possible sums of {3,5}
- possible = {0,3}∪{0+5,3+5}={0,3,5,8}
- Step 3: obtain all possible sums of {3,5,−1}
- possible = {0,3,5,8}∪{0−1,3−1,5−1,8−1}={−1,0,2,3,4,5,7,8}
Subset sum - live demo
Longest Increasing Subsequence
Longest Increasing Subsequence
- Find a subsequence of a given sequence in which the subsequence elements are in increasing order, and in which the subsequence is as long as possible
- This subsequence is not necessarily contiguous nor unique
- The longest increasing subsequence problem is solvable in time O(n∗log(n)) [more info]
- We will review one simple DP algorithm with complexity O(n∗n)
- Example: 1, 8, 2, 7, 3, 4, 1, 6
Longest Increasing Subsequence
- Find a subsequence of a given sequence in which the subsequence elements are in increasing order, and in which the subsequence is as long as possible
- This subsequence is not necessarily contiguous nor unique
- The longest increasing subsequence problem is solvable in time O(n∗log(n)) [more info]
- We will review one simple DP algorithm with complexity O(n∗n)
- Example: 1, 8, 2, 7, 3, 4, 1, 6
Longest Increasing Subsequence
Longest Increasing Subsequence
LIS - Dynamic table
LIS - Restore sequence
Longest Common Subsequence
Longest Common Subsequence
- Given two sequences x[1..m] and [1..n], find their longest common subsequence (LCS)
- For example if we have
- x="ABCBDAB"
- y="BDCABA"
- longest common subsequence will be "BCBA"
- For example if we have
Initial LCS table
- To compute the LCS efficiently using dynamic programming we start by constructing a table in which we build up partial results
- S1 = GCCCTAGCG
- S2 = GCGCAATG
Initial LCS table
- We'll fill up the table from top to bottom, and from left to right
- Each cell = the length of an LCS of the two string prefixes up to that row and column
- Each cell will contain a solution to a sub-problem of theoriginal problem
LCS table – base cases filled in
- Each empty string has nothing in common with any other string, therefore the 0-length strings will have values 0 in the LCS table
- Integer arrays in C# are filled with 0 by default, so we're good to go
LCS - live demo
LCS - live demo - reconstruct
Summary
Summary
- Divide-and-conquer method for algorithm design
- Dynamic programming is a way of improving on inefficient divide-and-conquer algorithms
- Dynamic programming is applicable when the sub-problems are dependent, that is, when sub-problems share sub-sub-problem
- Recurrent functions can be solved efficiently
- Longest increasing subsequence and Longest common subsequence problems can be solved efficiently using dynamic programming approach
DP Applications
- Matematical, finance and economic optimizations
- Optimal consumption and saving
- The core idea of DP is to avoid repeated work by remembering partial results. This is a very common technique whenever performance problems arise
- Bioinformatics
- sequence alignment, protein folding, RNA structure prediction and protein-DNA binding
DP Applications
- Control theory, information theory
- Operations research, decision making
- Computer science:
- Theory, Graphics, AI
- Markov chains
- Spelling correction
Questions?
Dynamic Programming Telerik Academy Alpha DSA
[C# DSA] Dynamic Programming
By telerikacademy
[C# DSA] Dynamic Programming
- 1,165