~/Dynamic Programming

Brandon Rozek

Photo of Brandon Rozek

PhD Student @ RPI studying Automated Reasoning in AI and Linux Enthusiast.

The book first goes into talking about the complexity of the Fibonacci algorithm

  if n = 0
    return 0
  else if n = 1
    return 1
    return RecFibo(n - 1) + RecFibo(n - 2)

It talks about how the complexity of this is exponential.

“A single call to RecFibo(n) results in one recursive call to RecFibo(n−1), two recursive calls to RecFibo(n−2), three recursive calls to RecFibo(n−3), five recursive calls to RecFibo(n−4)

Now consider the memoized version of this algorithm…

  if n = 0
    return 0
  else if n = 1
    return 1
    if F[n] is undefined:
      F[n] <- MemFibo(n - 1) + MemFibo(n - 2)
    return F[n]

This actually makes the algorithm run in linear time!


Dynamic programming makes use of this fact and just intentionally fills up an array with the values of $F$.

  F[0] <- 0
  F[1] <- 1
  for i <- 2 to n
    F[i] <- F[i - 1] + F[i - 2]
  return F[n]

Here the linear complexity becomes super apparent!

Interesting snippet

“We had a very interesting gentleman in Washington named Wilson. He was secretary of Defense, and he actually had a pathological fear and hatred of the word research. I’m not using the term lightly; I’m using it precisely. His face would suffuse, he would turn red, and he would get violent if people used the term research in his presence. You can imagine how he felt, then, about the term mathematical…. I felt I had to do something to shield Wilson and the Air Force from the fact that I was really doing mathematics inside the RAND Corporation. What title, what name, could I choose?”

Dynamic programming is essentially smarter recursion. It’s about not repeating the same work.

These algorithms are best developed in two distinct stages.

(1) Formulate the problem recursively.

(a) Specification: What problem are you trying to solve?

(b) Solution: Why is the whole problem in terms of answers t smaller instances exactly the same problem?

(2) Find solutions to your recurrence from the bottom up

(a) Identify the subproblems

(b) Choose a memoization data structure

(c) Identify dependencies

(d) Find a good evaluation order

(e) Analyze space and running time

(f) Write down the algorithm

Greedy Algorithms

If we’re lucky we can just make decisions directly instead of solving any recursive subproblems. The problem is that greedly algorithms almost never work.