![]() |
VOOZH | about |
We know that Dynamic Programming is a way to reduce the time complexity of a problem using memoization or tabulation of the overlapping states. While applying DP on arrays the array indices act as DP states and transitions occurs between indices.
Table of Content
Before coding the solution, we need to verify whether the time complexity of our solution fits the given constraints or not, we can approximate the time complexity using the below formula:
Time Complexity = Total Number of States * ( 1 + Average number of Transitions per State)
Space Complexity = Average number of States.
The problems that we see on Competitive Programming platforms are mainly made up of two parts:
- Adhoc part
- Standard part
The Adhoc part of the problem is the one that makes each problem unique and also the one that decides the difficulty of the problem. One needs to make several observations to deduce the Adhoc part into the standard solution. Good dp problems will often require you to make adhoc observations to figure out some properties that allow you to apply dp on them.
Let's us see how an Adhoc problem changes a standard DP problem:
: You are given N tiles 1 to N, and initially you are standing at 1. In one move you can make a jump of either 1 or 2 in forward direction. Determine the total number of ways you can reach from tile 1 to tile N.
: N=4
: total 3 ways are possible
: 1->2->3->4
1->2->4
1->3->4
: The Adhoc part of the problem diverts the question towards thinking of moving on tiles from 1 to N in different ways, the programmer will dry run several test cases and make several observations in order to reach to the solution, he might even try to make some mathematical formula to calculate the solution.
: If observed carefully this question is nothing but print the N'th fibonacci number the simplest DP problem that might exist. each tile T can be reached only via previous two tiles that is T is dependent upon T-1 and T-2. Using This we can write the DP states as:
- Number _of_ways[i]= Number _of_ways[i-1] + Number _of_ways[i-2]
The recurrence relation for the factorial of a number n is given by:
- Factorial [n] = factorial[n-1] * n
The recurrence relation for the inverse factorial of a number n is given by:
- Inverse_fact[n] = (n+1) * (inverse_fact[n+1])
When tackling DP problems during a contest the most difficult task is to define the states and transitions for the problem. The states and transitions for problems are mostly the variations of existing standard DP problems, let us see how we can try to think towards a particular standard DP problem:
Transition:
- If characters s1[i] and s2[j] are the same: dp[i][j] = dp[i-1][j-1].
- Otherwise: dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1.
The transitions in Edit distance are very commonly seen in many questions where a particular dp value depends upon previously calculated adjacent dp cells.
Transition:
- If characters s1[i] and s2[j] are the same: dp[i][j] = dp[i-1][j-1] + 1.
- Otherwise: dp[i][j] = max(dp[i-1][j], dp[i][j-1]).
Similar to Edit distance, LCS transitions can also be very frequently observed in various problems.
Problem | Practice Link |
|---|---|
Count number of coins required to make a given value (Coin Change II) | |
Save Your Life | |