See all coding puzzles and patterns here.
Algorithm Description
Dynamic programming is a programming technique wherein a larger problem is broken down into a smaller subproblem plus a computation for the remainder of the problem.
DP algorithms generally construct a solution vector, which can be multidimensional, starting with a base case
and then building on that base case up toward the solution.
Once the target solution is constructed, it is returned.
The solution vector is generally called dp
.
Example
For example, to solve the unbounded knapsack problem, we construct a solution vector dp
of length
t
equal to the target sum, where dp[i]
indicates the number of ways that i
can be
constructed using a sum of any of the available numbers.
We start with the base case dp[0] = 1
because 0 can be constructed in only one way, by using none of the elements.
Next we iterate over each element i
in dp
to compute the new j
that can be
attained by adding each number in the available numbers to i
.
If dp[i]
is equal to 0, then we skip any additions because i
cannot be attained,
implying that no sums can be constructed with i
as the base.
For each number that can be attained, we add dp[i]
to the existing value at dp[j]
.
The iteration over the dp
is continued until the target sum t
is computed in dp[t]
.
If we have a target of 10 and available numbers 2 and 4, and we want to know the number of ways 10 can be constructed as a sum of the available numbers, then the construction will look like:
setup: dp = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
i = 0: dp = [1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
i = 1: dp = [1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
i = 2: dp = [1, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0]
i = 3: dp = [1, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0]
i = 4: dp = [1, 0, 1, 0, 2, 0, 3, 0, 2, 0, 0]
i = 5: dp = [1, 0, 1, 0, 2, 0, 3, 0, 2, 0, 0]
i = 6: dp = [1, 0, 1, 0, 2, 0, 3, 0, 5, 0, 3]
i = 7: dp = [1, 0, 1, 0, 2, 0, 3, 0, 5, 0, 3]
i = 8: dp = [1, 0, 1, 0, 2, 0, 3, 0, 5, 0, 8]
i = 9: dp = [1, 0, 1, 0, 2, 0, 3, 0, 5, 0, 8]
The total permutations of 2 and 4 that can sum to 10 are:
2 + 2 + 2 + 2 + 2
2 + 2 + 2 + 4
2 + 4 + 4
2 + 2 + 4 + 2
2 + 4 + 2 + 2
4 + 2 + 2 + 2
4 + 2 + 4
4 + 4 + 2
If wanted to know the combinations adding to the target (i.e., only 2 + 2 + 2 + 2 + 2
,
2 + 2 + 2 + 4
and 2 + 4 + 4
) then we should store each combination as a set at each location
instead of just the number of permutations that add to that number.
In such a solution, we would initialize dp
with every element set to an empty array, which would be
equivalent to a value of 0
in the permutations solution above, and then set dp[0]
to an array
containing the empty set, which would be equivalent to the value 1
in the permutations solution above.
We would then add the newest element to the existing sets at each i
and append the new set to the existing
array at the new sum.
The sequence would then be:
setup: dp = [[()], [], [], [], [], [], [], [], [], [], []]
i = 0: dp = [[()], [], [(2)], [], [(4)], [], [], [], [], [], []]
i = 1: dp = [[()], [], [(2)], [], [(4)], [], [], [], [], [], []]
i = 2: dp = [[()], [], [(2)], [], [(4), (2, 2)], [], [(4, 2)], [], [], [], []]
i = 3: dp = [[()], [], [(2)], [], [(4), (2, 2)], [], [(4, 2)], [], [], [], []]
i = 4: dp = [[()], [], [(2)], [], [(4), (2, 2)], [], [(4, 2), (2, 2, 2)], [], [(4, 4)], [], []]
i = 5: dp = [[()], [], [(2)], [], [(4), (2, 2)], [], [(4, 2), (2, 2, 2)], [], [(4, 4)], [], []]
i = 6: dp = [[()], [], [(2)], [], [(4), (2, 2)], [], [(4, 2), (2, 2, 2)], [], [(4, 4), (4, 2, 2), (2, 2, 2, 2)], [], []]
i = 7: dp = [[()], [], [(2)], [], [(4), (2, 2)], [], [(4, 2), (2, 2, 2)], [], [(4, 4), (4, 2, 2), (2, 2, 2, 2)], [], []]
i = 8: dp = [[()], [], [(2)], [], [(4), (2, 2)], [], [(4, 2), (2, 2, 2)], [], [(4, 4), (4, 2, 2), (2, 2, 2, 2)], [], [(4, 4, 2), (4, 2, 2, 2), (2, 2, 2, 2, 2)]]
i = 9: dp = [[()], [], [(2)], [], [(4), (2, 2)], [], [(4, 2), (2, 2, 2)], [], [(4, 4), (4, 2, 2), (2, 2, 2, 2)], [], [(4, 4, 2), (4, 2, 2, 2), (2, 2, 2, 2, 2)]]
Puzzles
Puzzle | Difficulty | External Link |
0-1 Knapsack | Medium | |
Biggest Square in City Skyline | Medium | |
Distinct Subsequences | Medium | |
Find Number of Palindromic Substrings in a String | Medium | |
Longest Common Subsequence | Medium | Leetcode 1143 |
Longest Common Substring | Medium | |
Longest Increasing Subsequence | Medium | Leetcode 300 |
Sums from Weighted Words | Medium |