Dynamic Programming Flashcards
Longest common subsequence
Dp[m+1][n+1]
First row and first column 0 as empty string
Check if last characters match. If they match then dp[i][j]= dp[i-1][j-1]
Else
You have two options. You can check lcs with whole of string 1 and string2 upto last but one char and vice versa.
Dp[i][j]=max(dp(i-1,j) dp(i,j-1)
Return dp(m,n)
Coin change
Given an array of coin types we need to find out the total possible ways of getting the given sum
We have to choices. Either we include the last coin or we don’t. We can include it only if it’s value is less than sum
Dp(sum+1, n+1)
So when we don’t include
Dp(i,j)=dp(i, j-1)
Additionally if value is les than sum we can include it
Dp(i,j)+= dp(i-coins(j),j)
J and not j-1 cause repetitions of coins are allowed.
Return dp(sum, n)
Edit distance
Given two strings S1 nd S2, find the minimum number of operations to convert S1 to S2
Insert, del, replace
Dp(m+1, n+1)
Base cases if i=0 or j=0, return j and i resp
Else
If last char match, then dp(i,j)= dp(i-1, j-1)
Else
We will do one operation. So +1
Replace m-1, n-1
Del m-1, n
Insert m, n-1
So dp(i,j) =1+ min( dp(i-1,j-1), dp(i-1, j), dp(i,j-1))
Longest increasing subsequence
The idea is to find lis of subsequence ending with the current element
Inc order n
Dec order 1
Lis(0)=0 For i =1 to n-1 We are sunbsequences ending with i For j from0 to i-1 If arr[j]< arr[i] Then lis(i)= max(lis(j)+1, lis(i))
Now traverse through whole of lis array and find the max and return it
Why j is needed
If we do not consider j and just do lis(i) = lis(i-1)+1 we would be considering only those subsequences which end with arr(i-1) as well
0-1 Knapsack problem
Given an array of weights and another array of values, and Knapsack cap, we have to find max value such that the total weight doesn’t exceed knapsack capacity.
Dp(n+1,w+1)
Dp(i,j) is Max value which can be obtained with first i items and with knapsack cap j
Again, consider the last item
We have two cases. If it’s weight is more than cap, then we can’t consider it dp(i,j)=dp(i-1,j)
Else even now we have the option of either considering it or not and we choose whatever is Max
Dp(i,j) is Max(dp(i-1,j) , dp(i-1, j-wt(i))+Val(i-1))
Optimal strategy for game
Given even number of coins, you and your opponent can pick only corner coins. How can you make sure that you will always win?
We want the func to return our value.
How do we return our value when the opponent call the func? Opponent will chose his maximum and gives us a minimum value.
Base case, if there are only two values, return the max of the two
Dp[n][n]
For i from 0 to n-1
Dp(i,i+1)=max(arr(i),arr(i+1))
I is start index and j is end index. I>j
So we don’t have to fill lower half of the dp table.
We have two choices.
First pick ith coin. Opponent will have 2 cases either i+1 . In that case return us i+2 to j or he picks j, and returns us i+1 to j-1
Arr[i] +min(dp(i+2,j), dp(i+1, j-1)
Or we pick j
Arr(j) + min(dp(i+1,j-1) , dp(i,j-2))
Dp(i,j) will be max of these two
Final ans will be at dp(0,n-1)
Minimum deletions to make an array sorted
N-lis
Maximum sum increasing subsequence
Out of all increasing subsequences we need to find the one with max sum
Same as lis, instead of just storing the max length in lis array, we store the sum
Lis(i)=arr(i)
For j from 0 to i
Lis(i)= max( lis(j)+arr(i), lis(i))
And then traverse through lis array and find the maximum
Maximum length of bitonic subsequence
Bitonic sequence is one which first increases and then decreases.
We find the longest increasing subsequence ending with every element. That gives us the increasing part upto the pivot element. Now we need to find the length of the longest decreasing subsequence that begins with every element. For this LDS we have to traverse from right.
Max(lis(i)+LDS(i)+1) is the ans
Building bridges
Maximize the number of bridges we can build, such that no two of them cross.
You are given a list of bridges with their start and end points on two sides of the river
First sort all pairs in increasing order of first value
If two first values are same then consider second value
Find lis of sorted array according to second value
Starting points are already sorted. If the ending points are also in increasing order then there won’t be any crosses. So we cal lis which is nothing but longest increasing subsequence
Longest chain of pairs
Given a list of pairs where in each pair a<b></b>
Sort the array in the increasing order of first value
Now find lis with the only change that arr(i).first > arr(j).second in lis condition
Minimum insertions and deletions to convert S1 to S2
Find lcs of S1 and S2 S1 length m S2 length n Lcs l M-l deletions N-l insertions M+n-2l
Shortest common supersequence
Given two strings, we have to find a third string containing the two and is the shortest
Once we have lcs we traverse the first string and insert extra characters in order. And then traverse the second and insert the extra char
Need printing or storing of lcs
Longest palindromic subsequence
To find longest palindromic subsequence we have to reverse the given string to get S2. Then the length of longest palindromic subsequence is nothing but lcs of S1 and S2
Longest repeating subsequence
Same as lcs but with an additional condition that last char match and their indexes are not the same
Printing lcs
We can use our 2 d array to print the actual lcs. We can traverse the 2 d array from bottommost right most corner and whenever we see matching char, we move along the diagonal and print. Else we take maximum of upper and lower and in this case we don’t print the char
Minimum jumps to reach end
Given an array where every elements represents the max number of jumps that can be made from that point in the array
Greedy solution will not work.
We have to traverse from back and see from where we can reach end
Then num of jumps will be 1+ the number of jumps to reach that position.
The minimum possible such answer is what we want
For i from 0 to n-1 For j from 0 to i If (arr(j)+j>=i) If(dp(i) not equal to int_max Then dp(i) =min(dp(i), dp(j)+1)
Min coins to make a value, given infinite supply of every coin type in the set
Dp[Val+1] Dp[0]=0 Initially dp array is infinite For int i=1 to Val For j from 0 to n If(arr(j)<i></i>
Egg dropping puzzle
Find the minimum number of egg dropping trials needed to find the threshold floor
At a given floor there are two cases. Either the egg breaks or it doesn’t.
If the egg breaks we will have to check for all floors below. If it doesn’t, we will have to check for thresholds above this current floor
Res(f,e)= min( max(breaks, doesn’t break))
Min because we want the minimum floor and maximum because we consider the worst case possibility from the current floor.
Res(f,e) =min(max(res(x-1,e-1), res(f-x,e))+1
Base cases res(f,1)=f
Res(0,e)=0
Res(1,e)=1
Dp[f+1][e+1]
Fill first row with zero as f is 0
Similarly fill second column with i as number of eggs is 1 as you will try from below
Now for every other value i, j,. I representing floor and j the number of eggs
Dp(i,j)=int_max
For (x=1, x<=i; x++)
Dp(i,j)=min(dp(i,j), max(dp(x-1,j-1),dp(f-x, j))
Return dp(f,e)
Count BST
Given a number n, we have to consider n distinct keys and count the number of unique bsts we can make from those keys. The value of keys doesn’t matter
Say n is 5
1 2 3 4 5
We can consider 1 as root. Then 0 elements on left and n-i-1 elements on right. Next 2 as root and so on..
Res(n)= sum from i=0 to n-1
Res(i)*res(n-i-1)
This is the logic
Dp[n+1] For int i=1 to n Dp(i)=0 For j from 0 to i Dp(i)+= dp(j)*dp(i-j-1)
Return dp(n)
Maximum sum with no 2 consecutives
Again considering from last element
There are two cases. You either consider this element or you don’t. If you consider you can’t consider the element before it
Dp(i)=max( dp(i-2)+arr(i), dp(i-1))
Can be space optimised as we do not need the entire dp array. We only need prev and prev_prev
Number of subsets with given sum
dp[n][sum]
We begin from the lasst element. We either include it or not
If arr(n-1) > sum then only one case .
Don’t include return count (sum, n-1)
Need to check the above condition first to ensure that the sum is not negative. Cause in dp index cannot be negative.
Else (count(sum,n-1) + count( sum-arr(n-1), n-1))
Matrix chain multiplication
Given an array of size n which represents n-1 matrices, find the minimum num of element multiplications needed to multiply all of them together
To multiply matrices of size (i,j) (j,k) we need jik number of multiplications.
Now we can make the first partition in number of ways from index 1 to n-1.
Dp[n][n]
Dp(i,j) stores the result for subarray from index i to j
We cannot just fill the dp array row wise. We use gap method where we fill diagonally
Base case when I+1=j meaning only one matrix, for that we don’t have to multiply. So 0
For (i from 0 to n-1)
Dp(i,i+1)=0
For (int gap=2 gap less n, gap++)
For (i from 0 to gap+i less then n)
J =i+gap
For k from i+1 to j
Dp(i,j)=min(dp(i,j), dp(i,k)+dp(k,j)+ arr(i)arr(j)arr(k))
Return dp(0,n-1)
Palindrome partitioning
Given a string we have to make minimum cuts in the string so that all parts are palindromic
If our string is already palindrome we return 0 this is one of the base case.
If the string is not palindrome, then we need to make some partitions.
We try making our first partition in all possible places and recursively call on the left and right partitions and add 1. When we make the first partition in all possible ways, we track the min and return the minimum of all answers.
Dp(i,j) stores the min cuts required for the substring i to j
Since dp array dimensions correspond to start and end index, we follow gap method.
Lower half not needed as start index is always greater than end index
For gap from 1 to n For i from 0 to gap+i less than n J= gap+i Firstly check if it is palindrome Dp(i,j)=0 Else Dp(i,j)=inf For k=1 to j Dp(i,j)= min(dp(i,j), 1+dp(i,k)+dp(k+1,j)
Ret dp(0,n-1)
Allocate min pages
Given number of pages in n books, and k students who are supposed to read all the books, we need to minimise the maximum number of pages that can be alloted under the constraint that only continuous pages can be alloted to a student
We need to choose k-1 cuts out of n-1 cuts.
We can choose any of the n-1 cuts as our first cuts and assign one side to one student and the other part to k-1 students
For every possible first partition
Res=min(res, max( sum(arr,i n-1) ,minpages(arr, i ,k-1))
Sum is how many pages will that one student read and we want maximum as we want max pages.
We use min as we need to minimise the maximum pages for every possible first partition.
Dp(n,k) Dp(i,j) is min of max pages with i people and j books Dp(1,i) is sum as only one student Dp(i,1) = arr(0) For i from 2 to k For j from 2 to n Int res =inf For p from i+1 to j Res=min( res, max(dp(i-1,p), sum(arr,p,j-1)) Dp(i,j) =res
Ret dp(k,n)
Maximum cuts
Given a rod of length n and 3 values a,b,c, we want to make maximum cuts in this rod such that length of every cut should be either a b or c.
Dp(n+1) Dp(0)=0 For i from 1 to n Dp(i)=-1 If i-a >0 then dp(i)=max(dp(i), dp(i-a)) Similarly for b and c If dp(i) not equal to -1 dp(i)++
Return d(n)
Scrambled strings
Given a string a we can represent it as a bt, partitioning it into 2 non empty substrings recursively. To scramble a string we choose any non leaf node and swap it’s 2 children.
Given two strings a and b of same length determine if b is a scrambled string of a.
We use a map to keep track of cases we have already visited
Base case if both the strings are equal , return map of S1+#+S2 as true.
If size is one and not equal, they cannot be scrambled counterparts.
So return map of S1+#+s2 false
If we have already visited this case then return the ans stored.
We can make the first partition in any of the positions from 1- n-1
We have 2 cases
Case 1: when we check blocks 1 of both S1 and S2 and blocks 2 of both S1 and S2.:if they match then yes, they are scrambled counterparts.
Bool cond1
Case 2 when we check block 1 of S1 and block 2 of S2 and block 2 of S1 and block 1 of S2.
If either condition 1 or 2 is true we return map of S1+#+S2 as true
Else false
Distinct sequences
Given two sequences a and b cunt number of unique ways in sequence a to form a subsequence that is identical to b
Choices(s,t,n,m, i,j)
Base cases when j ==m ret1. While string t has been processed and we have an answer
If i==n ret 0 if s becomes empty string then we cannot achieve ans
If the first chat match, then we have 2 choices. We can either consider the first chat or not. If we consider then we increase both i and j. If we don’t, then we increase i but not j.
If the first char do not match, the we have only one choice of not including it i+1, j
In dp solution we do the same thin in a bottom up manner Dp(m,n) If ast char match, Dp(i,j)= Dp(i-1,j-1)+dp(i-1,j) Else Dp(i,j) =dp(i-1,j)
Return dp(m,n)
Smallest sequence with given primes
Given 3 prime numbers a, b and c and an integer d, you have to find the first smallest inter
Dp(0)=0 Int P1=0, int P2=0 P3 also 0 For i from 0 to d A_mul= dp(P1)*a Similarly b and c Dp(i) is min of these Increment the pointer of that min