notes-2
notes-2
∗
Hoa T. Vu
1 Introduction
The main ideas behind dynamic programming are as follows. Dynamic programming is basically
smart recursion. One may think of dynamic programming as recursion with memoization.
T (n) = T (n − 1) + T (n − 2) + O(1) ≤ 2T (n − 1) + c
Exercise: Use recursion tree method to show that the running time is Ω(2n ).
Why is the above algorithm wasteful? That’s because there is a lot of repeated computation.
fib(5)
fib(4) fib(3)
fib(1) fib(0)
∗
San Diego State University, [email protected]
1
So, we try to avoid repeated computation by checking if the computation has been done before.
Algorithm 2: Dynamic Programming (top down) for computing the nth Fibonacci number
1 Initialize F [1 . . . n] where each entry is NULL.
2 Function ComputeFibonacci(i)
3 if i = 0 then return 0
4 else if i = 1 then return 1
5 else if F [i − 1] = N U LL then ComputeFibonacci(i − 1)
6 if F [i − 2] = N U LL then ComputeFibonacci(i − 2)
7 Return F [i − 1] + F [i − 2]
8 Call ComputeFibonacci(n).
The above approach is call top-down. We can also fill the array F bottom up deliberately.
Algorithm 3: Dynamic Programming (bottom up) for computing the nth Fibonacci
number
1 Initialize F [1 . . . n] where each entry is NULL.
2 F [0] = 0, F [1] = 1.
3 for i = 2, 3, . . . , n do
4 F [i] = F [i − 1] + F [i − 2].
5 end for
The running time is O(n) which is a great improvement over naive recursion.
The goal is to compute dist[1 . . . n] where dist[i] is the length of the shortest path from v1 to vi .
• Clearly, dist[1] = 0.
• Consider any node vi . The shortest path from v1 to vi (denoted by v1 vi ) must go through
some vi predecessor vj (ie, j < i where there is an edge vj → vi ) and then then go from vj to
vi using the edge vj → vi (it is possible that vj = v1 if there is an edge from v1 to vi ).
2
• If v1 vi goes through vj before going from vj to vi using the edge vj → vi , then the length
of that path would be the length of the shortest path v1 vj plus the length of the edge
vj → vi .
• Thus,
dist[vi ] = min (dist[vj ] + `(vj , vi )).
j<i:vj →vi ∈E
• L[1] = 1.
• Consider any node i. The longest path ending at i must go through some vi predecessor vj (ie,
j < i where there is an edge vj → vi ) and then then go from vj to vi using the edge vj → vi .
If i has no predecessor, then the longest path ending at i is just i itself.
• Thus, (
maxj<i (L[j] + 1) if there is some j s.t A[j] ≤ A[j]
L[i] =
1 otherwise
3
Algorithm 5: Dynamic programming for longest increasing subsequence
1 Initialize L[1 . . . n] where each entry is 1.
2 L[1] = 1.
3 for i = 2, 3, . . . , n do
4 max = 1
5 for j = 1, 2, . . . , i − 1 do
6 if A[j] ≤ A[i] and L[j] + 1 > max then
7 max = L[j] + 1
8 end if
9 end for
10 end for
5 Common theme
There are a few things that we should consider when designing a dynamic programming algorithm.
6 Edit distance
We are given 2 input strings A and B of length n and m respectively. What is the minimum number
of insertions, deletions, and replacements to transform A into B?
Example 2. Let’s consider the same 2 strings, but a different set of edits. The below corresponds
to 1) insert S in the beginning 2) Replace S with U, and 3) Delete O, 4) Delete W, 5) insert N.
There are 5 edits in total.
S N O W Y
S U N N Y
The question is to place the gaps that correspond to the smallest number of edits which is the
edit distance between A and B.
4
A DP approach. We define the dynamic programming table as follows.
7 Knapsack
Let us assume that we have n items (without repetition) each of which has a weight w[i] and a
value v[i]. We are allowed to carry at most W unit of weight in total. Assume weights and values
are all integers, how to pick items to carry such that we maximize the value?
5
Applications: This arises in various problems where values correspond to utilities and B corre-
sponds to some resource constraints.
The greedy algorithm that picks items with highest value/weight fails to find the best solution.
For example, consider the input W = [3, 2, 2], V = [1.65, 1, 1], B = 4.
Let T [i, j] be the maximum value that we can carry using j unit of weights from items 1, . . . , i.
The optimal solution has to either we pick item i or we don’t.
If we pick item i, the largest total value we could get is T [i − 1, j − w[i]] + V [i]. If we do not
pick item i, the largest total value we could get is T [i − 1, j].
Algorithm 7: Dynamic programming for Knapsack without repetition
1 For each i = 0, 1, 2, . . . , n: T [i, 0] = 0
2 For each j = 0, 1, 2, . . . , B: T [0, j] = 0.
3 for i = 1, 3, . . . , n do
4 for j = 1, 2, . . . , B do
5 if W [i] ≤ j then
6 T [i, j] = max{T [i − 1, j − W [i]] + V [i], T [i − 1, j]}.
7 else
8 T [i, j] = T [i − 1, j]
9 end if
10 end for
11 end for
12 Return T [n, B].
It is easy to see that the running time is O(nB).
8 Subset Sum
Consider a multiset A of n positive integers (represented as an array A[1 . . . n]). We want to output
true if there is a subset of A that sum to a target integer T .
Convention: empty subset sums to 0.
Let S[i, j] = true if and only if there is a subset of A[1 . . . i] that sums to j. Suppose there is a
subset of A that sum to j. There are 2 cases:
• Case 1: This subset contains A[i] which means there must be a subset of A[1 . . . i − 1] that
sum to j − A[i]. Therefore, if this is the case, then S[i − 1, j − A[i]] = true.
• Case 1: This subset does not A[i] which means there must be a subset of A[1 . . . i − 1] that
sum to j. Therefore, if this is the case, then S[i − 1, j] = true.
Therefore, S[i, j] = true if and only if S[i − 1, j − A[i]] = true or S[i − 1, j] = true.
6
Algorithm 8: Dynamic programming for subset sum
1 Corner cases:
2 S[0, 0] = true
3 S[0, j] = f a`se for all j = 1, 2, . . . , T
4 for i = 1, 3, . . . , n do
5 for j = 1, 2, . . . , T do
6 if A[i] ≤ j then
7 S[i, j] = S[i − 1, j − A[i]] ∨ S[i − 1, j] = true
8 else
9 S[i, j] = S[i − 1, j] = true
10 end if
11 end for
12 end for
13 Return T [n, T ].
It is easy to see that the running time is O(nT ).
7
The running time is O(n2 ) since each T [i, j] is called at most once and the non-recursive work is
O(1).
Exercise: How to implement this bottom-up?