Skip to content

What is dynamic programming

Dynamic programming is a method for solving a complex problem by breaking it down into a collection of simpler subproblems, solving each of those subproblems just once, and storing their solutions.

The next time the same subproblem occurs, instead of recomputing it's solution, one simply looks up the previously computed solution, thereby saving computation time at the expense of a modest expenditure in storage space.

Dynamic programming is mainly and optimization over plain divide and conquer.

Top Down approach

We can use Fibonacci series for an example.

FibonacciRecursive(n)
    if(n < 1) return error
    else if (n == 1) return 0
    else if (n == 2) return 1
    return FibonacciRecursive(n-1) + FibonacciRecursive(n-2)

Time complexity - O(1.6180)^n
Space complexity - O(n)

We can optimize this algorithm to memoize the results and increase the performance of the algorithm.

int FibonacciAux(int[] memoize, int n)
    if n < 1 return error
    else if n == 1 return 0
    else if n == 2 return 1

    if memoize[n] == 0
        memoize[n] = FibonacciAux(memoize, n-1) + FibonacciAux(memoize, n-2)

    return memoize[n]

The top down approach breaks the problem into smaller subproblems. Then, these subproblems are solved and stored into memory if any of them ever comes up again.

Bottom up approach

In bottom up approach, we evaluate the function starting with the smallest possible input arguement value and then we work our way up. While computing the values we store all the computed values in memory. As larger arguments are evaluated, precomputed values for smaller arguments can be reused.

Int this case all the subproblems that we might need in future are precomputed and then they are used to solve a bigger problem.

int FibonacciBottomUp(int n)

    create a new arrayTable[] of size n
    if n < 1 return error

    table[0] = 0
    table[1] = 1
    for(int i = 3; i < n; i++)
        table[i] = table[i-2] + table[i-3]
    return table[n]

Time Complexity - O(n)
Space Complexity - O(n)

Divide&Conquer vs Top Down vs Bottom Up

Problem Divide & Conquer Top Down Bottom Up
Fibonacci numbers O(1.6180)^n O(n) O(n)

Top down vs Bottom up methods

Top Down Bottom Up
Ease of algorithm Easy to come up with solution as it is an extension of Divide & Conquer Not so easy to come up with a solution
Run time of Algorithm Slow Fast
Space efficiency Unnecessary use of extra Stack space. Can run out of stack space if computation is huge. No stack is used
When to use Need a quick solution Need an efficient solution