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

 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 \( F_i = F_{i-1} + F_{i-2} \)

 Compare Fibonacci Solutions

  • Recursive solution
    • Complexity: ~O(φ\(^n\)) = O(1.618\(^n\))
  • 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

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\} \cup \{0+3\} = \{0,3\} \)
  • Step 2: obtain all possible sums of \( \{3,5\} \)
    • possible = \( \{0,3\} \cup \{0+5,3+5\} = \{0,3,5,8\} \)
  • Step 3: obtain all possible sums of \( \{3,5,-1\} \)
    • possible = \( \{0,3,5,8\} \cup \{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"

 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?

[C# DSA] Dynamic Programming

By telerikacademy

[C# DSA] Dynamic Programming

  • 1,063