DAA (Lecture 5)
DAA (Lecture 5)
Algorithms (CS-306)
Dynamic Programming
Lecture No. 5
The problem:
◦ Lots and lots of calls to Fib(1) and Fib(0) are made.
It would be nice if we only made those method calls once, then
simply used those values as necessary.
return fibnumbers[n];
}
Dynamic Programming
Usually, a dynamic programming
algorithm presents a time-space
trade off.
◦ More space is used to store values,
◦ BUT less time is spent because
these values can be looked up.
Dynamic Programming
Example Problems
◦ Longest Common Subsequence
Problem
◦ Edit Distance
◦ Binomial Coefficient
◦ Chain Matrix Multiplication Problem
◦ Knapsack 0-1 Algorithm
◦ Floyd Warshall Algorithm
◦ The Fibonacci example
◦ The Coin Change problem
Longest Common Subsequence
Problem
Theproblem is to find the longest
common subsequence in 2 given strings.
◦ “ODOR” is a subsequence
made up of the characters at indices 1, 3, 5, and 6.
LCS(“FU”, “FI”)
=1
◦ Last chars Do NOT match:
max(LCS(“FU”, “F”), LCS(“F”, “FI”)
= max (1 , 1) = 1
LCS(“FU”, “F”) LCS(“F”, “FI”)
Base case: return 1, since “F” is in “FU” return 1, since “F” is in “FI”
Longest Common
Subsequence
Now, our goal will be to take this
recursive solution and build a
dynamic programming solution.
◦ The key here is to notice that the heart
of each recursive call is the pair of
indexes, telling us which prefix string we
are considering.
◦ In some sense, we can build the answer
to "longer" LCS questions based on the
answers to smaller LCS questions.
◦ This can be seen trace through the
recursion at the very last few steps.
Longest Common
Subsequnce
Ifwe make the recursive call on the
strings RACECAR and CREAM,
◦ once we have the answers to the
recursive calls for inputs RACECAR and
CREA and the inputs RACECA and
CREAM,
◦ we can use those two answers and
immediately take the maximum of the
two to solve our problem!
Longest Common
Subsequence
Thus, think of storing the
answers to these recursive calls
in a table, such as this:
R A C E C A R
C
R
E
A XXX
M
return lengths[a.length()][b.length()];
}
Edit Distance
The Edit Distance (or Levenshtein
distance) is a metric for measuring the
amount of difference between two.
◦ The Edit Distance is defined as the
minimum number of edits needed to
transform one string into the other.
For
values of n and k that are not small,
we cannot compute the binomial
coefficient directly from this definition
because n! is very large even for
moderate values of n.
For simplicity the following relation is used
1)If d is 25, give out a quarter and make change for n-25 cents
using the largest coin as a quarter.
2)If d is 10, give out a dime and make change for n-10 cents using
the largest coin as a dime.
3)If d is 5, give out a nickel and make change for n-5 cents using
the largest coin as a nickel.
4)If d is 1, we can simply return 1 since if you are only allowed to
give pennies, you can only make change in one way.
The Change Problem
There's a whole bunch of stuff going on
here, but one of the things you'll notice
is that the larger n gets, the slower and
slower this will run, or maybe your
computer will run out of stack space.
◦ Further analysis will show that many, many
method calls get repeated in the course of
a single initial method call.
// Initialize table
for (int i=0; i<n+1;i++)
table[0][i] = 1;
for (int i=0; i<5; i++) {
table[1][i] = 1;
table[2][i] = 1;
table[3][i] = 1;
}
for (int i=5;i<n+1;i++) {
table[1][i] = 0;
table[2][i] = 0;
table[3][i] = 0;
// Fill in table, row by row. Remember,
for (int i=1; i<4; i++) { int[] denominations = {1, 5, 10, 25};
for (int j=5; j<n+1; j++) {
for (int k=0; k<=i; k++) {
if ( j >= denominations[k])
table[i][j] +=
table[k][j - denominations[k]];
}
}
}
return table[lookup(d)][n];
}
}