Dynamic Programming
Dynamic Programming
1
10 Set 10 ( 0-1 Knapsack Problem) 57
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
2
22 Set 22 (Box Stacking Problem) 116
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
3
34 Set 34 (Assembly Line Scheduling) 181
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
42 Count all possible paths from top left to bottom right of a mXn
matrix 221
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
44 Count even length binary sequences with same sum of first and
second half bits 229
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
4
45 Count number of binary strings without consecutive 1’s 236
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
54 Find minimum possible size of array with given rules for re-
moving elements 273
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
5
56 Find the longest path in a matrix with given constraints 281
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
58 How to print maximum number of A’s using given four keys 290
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
6
68 Minimum Initial Points to Reach Destination 339
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
7
79 Total number of non-decreasing numbers with n digits 399
Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
8
Chapter 1
Set 1 (Overlapping
Subproblems Property)
9
Recursion tree for execution of fib(5)
fib(5)
/ \
fib(4) fib(3)
/ \ / \
fib(3) fib(2) fib(2) fib(1)
/ \ / \ / \
fib(2) fib(1) fib(1) fib(0) fib(1) fib(0)
/ \
fib(1) fib(0)
We can see that the function f(3) is being called 2 times. If we would have stored
the value of f(3), then instead of computing it again, we would have reused the
old stored value. There are following two different ways to store the values so
that these values can be reused.
a) Memoization (Top Down):
b) Tabulation (Bottom Up):
a) Memoization (Top Down): The memoized program for a problem is similar
to the recursive version with a small modification that it looks into a lookup
table before computing solutions. We initialize a lookup array with all initial
values as NIL. Whenever we need solution to a subproblem, we first look into
the lookup table. If the precomputed value is there then we return that value,
otherwise we calculate the value and put the result in lookup table so that it
can be reused later.
Following is the memoized version for nth Fibonacci Number.
int lookup[MAX];
10
int i;
for (i = 0; i < MAX; i++)
lookup[i] = NIL;
}
return lookup[n];
}
int main ()
{
int n = 40;
_initialize();
printf("Fibonacci number is %d ", fib(n));
getchar();
return 0;
}
b) Tabulation (Bottom Up): The tabulated program for a given problem builds
a table in bottom up fashion and returns the last entry from table.
/* tabulated version */
#include<stdio.h>
int fib(int n)
{
int f[n+1];
int i;
f[0] = 0; f[1] = 1;
for (i = 2; i <= n; i++)
f[i] = f[i-1] + f[i-2];
return f[n];
11
}
int main ()
{
int n = 9;
printf("Fibonacci number is %d ", fib(n));
getchar();
return 0;
}
Source
http://www.geeksforgeeks.org/dynamic-programming-set-1/
12
Chapter 2
Set 2 (Optimal
Substructure Property)
13
We will be covering some example problems in future posts on Dynamic Pro-
gramming.
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
References:
http://en.wikipedia.org/wiki/Optimal_substructure
CLRS book
Source
http://www.geeksforgeeks.org/dynamic-programming-set-2-optimal-substructure-property/
Category: Misc Tags: Dynamic Programming
14
Chapter 3
/* To make use of recursive calls, this function must return two things:
15
1) Length of LIS ending with element arr[n-1]. We use max_ending_here
for this purpose
2) Overall maximum as the LIS may end with an element before arr[n-1]
max_ref is used this purpose.
The value of LIS of full array of size n is stored in *max_ref which is our final result
*/
int _lis( int arr[], int n, int *max_ref)
{
/* Base case */
if(n == 1)
return 1;
/* Recursively get all LIS ending with arr[0], arr[1] ... ar[n-2]. If
arr[i-1] is smaller than arr[n-1], and max ending with arr[n-1] needs
to be updated, then update it */
for(int i = 1; i < n; i++)
{
res = _lis(arr, i, max_ref);
if (arr[i-1] < arr[n-1] && res + 1 > max_ending_here)
max_ending_here = res + 1;
}
// returns max
return max;
}
16
/* Driver program to test above function */
int main()
{
int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
int n = sizeof(arr)/sizeof(arr[0]);
printf("Length of LIS is %d\n", lis( arr, n ));
getchar();
return 0;
}
lis(4)
/ | \
lis(3) lis(2) lis(1)
/ \ /
lis(2) lis(1) lis(1)
/
lis(1)
We can see that there are many subproblems which are solved again and again.
So this problem has Overlapping Substructure property and recomputation of
same subproblems can be avoided by either using Memoization or Tabulation.
Following is a tabluated implementation for the LIS problem.
17
lis[i] = 1;
return max;
}
getchar();
return 0;
}
Note that the time complexity of the above Dynamic Programmig (DP) solution
is O(nˆ2) and there is a O(nLogn) solution for the LIS problem (see this). We
have not discussed the nLogn solution here as the purpose of this post is to
explain Dynamic Programmig with a simple example.
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/dynamic-programming-set-3-longest-increasing-subsequence/
Category: Misc Tags: Dynamic Programming
18
Post navigation
← Set 2 (Optimal Substructure Property) A Boolean Array Puzzle →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
19
Chapter 4
20
If last characters of both sequences match (or X[m-1] == Y[n-1]) then
L(X[0..m-1], Y[0..n-1]) = 1 + L(X[0..m-2], Y[0..n-2])
If last characters of both sequences do not match (or X[m-1] != Y[n-1]) then
L(X[0..m-1], Y[0..n-1]) = MAX ( L(X[0..m-2], Y[0..n-1]), L(X[0..m-1], Y[0..n-2])
Examples:
1) Consider the input strings “AGGTAB” and “GXTXAYB”. Last characters
match for the strings. So length of LCS can be written as:
L(“AGGTAB”, “GXTXAYB”) = 1 + L(“AGGTA”, “GXTXAY”)
2) Consider the input strings “ABCDGH” and “AEDFHR. Last characters do
not match for the strings. So length of LCS can be written as:
L(“ABCDGH”, “AEDFHR”) = MAX ( L(“ABCDG”, “AEDFHR”),
L(“ABCDGH”, “AEDFH”) )
So the LCS problem has optimal substructure property as the main problem
can be solved using solutions to subproblems.
2) Overlapping Subproblems:
Following is simple recursive implementation of the LCS problem. The imple-
mentation simply follows the recursive structure mentioned above.
21
int main()
{
char X[] = "AGGTAB";
char Y[] = "GXTXAYB";
int m = strlen(X);
int n = strlen(Y);
getchar();
return 0;
}
Time complexity of the above naive recursive approach is O(2ˆn) in worst case
and worst case happens when all characters of X and Y mismatch i.e., length of
LCS is 0.
Considering the above implementation, following is a partial recursion tree for
input strings “AXYT” and “AYZX”
lcs("AXYT", "AYZX")
/ \
lcs("AXY", "AYZX") lcs("AXYT", "AYZ")
/ \ / \
lcs("AX", "AYZX") lcs("AXY", "AYZ") lcs("AXY", "AYZ") lcs("AXYT", "AY")
In the above partial recursion tree, lcs(“AXY”, “AYZ”) is being solved twice.
If we draw the complete recursion tree, then we can see that there are many
subproblems which are solved again and again. So this problem has Overlap-
ping Substructure property and recomputation of same subproblems can be
avoided by either using Memoization or Tabulation. Following is a tabulated
implementation for the LCS problem.
22
{
int L[m+1][n+1];
int i, j;
else
L[i][j] = max(L[i-1][j], L[i][j-1]);
}
}
int m = strlen(X);
int n = strlen(Y);
getchar();
return 0;
}
23
Time Complexity of the above implementation is O(mn) which is much better
than the worst case time complexity of Naive Recursive implementation.
The above algorithm/code returns only length of LCS. Please see the following
post for printing the LCS.
http://www.algorithmist.com/index.php/Longest_Common_Subsequence
http://www.ics.uci.edu/~eppstein/161/960229.html
http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
Source
http://www.geeksforgeeks.org/dynamic-programming-set-4-longest-common-subsequence/
24
Chapter 5
Given two strings str1 and str2 and below operations that can performed on
str1. Find minimum number of edits (operations) required to convert ‘str1� into
‘str2�.
1. Insert
2. Remove
3. Replace
Examples:
25
What are the subproblems in this case?
The idea is process all characters one by one staring from either from left or
right sides of both strings.
Let we traverse from right corner, there are two possibilities for every pair of
character being traversed.
1. If last characters of two strings are same, nothing much to do. Ignore last
characters and get count for remaining strings. So we recur for lengths
m-1 and n-1.
2. Else (If last characters are not same), we consider all operations on ‘str1�,
consider all three operations on last character of first string, recursively
compute minimum cost for all three operations and take minimum of three
values.
(a) Insert: Recur for m and n-1
(b) Remove: Recur for m-1 and n
(c) Replace: Recur for m-1 and n-1
26
// If second string is empty, the only option is to
// remove all characters of first string
if (n == 0) return m;
// Driver program
int main()
{
// your code goes here
string str1 = "sunday";
string str2 = "saturday";
return 0;
}
Python
27
# If second string is empty, the only option is to
# remove all characters of first string
if n==0:
return m
Output:
28
We can see that many subproblems are solved again and again, for example
eD(2,2) is called three times. Since same suproblems are called again, this prob-
lem has Overlapping Subprolems property. So Edit Distance problem has both
properties (see thisand this) of a dynamic programming problem. Like other
typical Dynamic Programming(DP) problems, recomputations of same subprob-
lems can be avoided by constructing a temporary array that stores results of
subpriblems.
C++
29
for (int i=0; i<=m; i++)
{
for (int j=0; j<=n; j++)
{
// If first string is empty, only option is to
// isnert all characters of second string
if (i==0)
dp[i][j] = j; // Min. operations = j
return dp[m][n];
}
// Driver program
int main()
{
// your code goes here
string str1 = "sunday";
string str2 = "saturday";
return 0;
}
Python
30
# A Dynamic Programming based Python program for edit
# distance problem
def editDistDP(str1, str2, m, n):
# Create a table to store results of subproblems
dp = [[0 for x in range(n+1)] for x in range(m+1)]
return dp[m][n]
# Driver program
str1 = "sunday"
str2 = "saturday"
Output:
31
3
Source
http://www.geeksforgeeks.org/dynamic-programming-set-5-edit-distance/
32
Chapter 6
Given a cost matrix cost[][] and a position (m, n) in cost[][], write a function
that returns cost of minimum cost path to reach (m, n) from (0, 0). Each cell of
the matrix represents a cost to traverse through that cell. Total cost of a path
to reach (m, n) is sum of all the costs on that path (including both source and
destination). You can only traverse down, right and diagonally lower cells from
a given cell, i.e., from a given cell (i, j), cells (i+1, j), (i, j+1) and (i+1, j+1)
can be traversed. You may assume that all costs are positive integers.
For example, in the following figure, what is the minimum cost path to (2, 2)?
The path with minimum cost is highlighted in the following figure. The path is
(0, 0) –> (0, 1) –> (1, 2) –> (2, 2). The cost of the path is 8 (1 + 2 + 2 + 3).
33
1) Optimal Substructure
The path to reach (m, n) must be through one of the 3 cells: (m-1, n-1) or (m-1,
n) or (m, n-1). So minimum cost to reach (m, n) can be written as “minimum
of the 3 cells plus cost[m][n]”.
minCost(m, n) = min (minCost(m-1, n-1), minCost(m-1, n), minCost(m, n-1))
+ cost[m][n]
2) Overlapping Subproblems
Following is simple recursive implementation of the MCP (Minimum Cost Path)
problem. The implementation simply follows the recursive structure mentioned
above.
34
minCost(cost, m-1, n),
minCost(cost, m, n-1) );
}
It should be noted that the above function computes the same subproblems
again and again. See the following recursion tree, there are many nodes which
apear more than once. Time complexity of this naive recursive solution is expo-
nential and it is terribly slow.
mC refers to minCost()
mC(2, 2)
/ | \
/ | \
mC(1, 1) mC(1, 2) mC(2, 1)
/ | \ / | \ / | \
/ | \ / | \ / | \
mC(0,0) mC(0,1) mC(1,0) mC(0,1) mC(0,2) mC(1,1) mC(1,0) mC(1,1) mC(2,0)
So the MCP problem has both properties (see thisand this) of a dynamic pro-
gramming problem. Like other typical Dynamic Programming(DP) problems,
recomputations of same subproblems can be avoided by constructing a tempo-
rary array tc[][] in bottom up manner.
35
C++
tc[0][0] = cost[0][0];
return tc[m][n];
}
36
/* Driver program to test above functions */
int main()
{
int cost[R][C] = { {1, 2, 3},
{4, 8, 2},
{1, 5, 3} };
printf(" %d ", minCost(cost, 2, 2));
return 0;
}
Python
tc[0][0] = cost[0][0]
return tc[m][n]
37
# Driver program to test above functions
cost = [[1, 2, 3],
[4, 8, 2],
[1, 5, 3]]
print(minCost(cost, 2, 2))
Output:
Source
http://www.geeksforgeeks.org/dynamic-programming-set-6-min-cost-path/
38
Chapter 7
Given a value N, if we want to make change for N cents, and we have infinite
supply of each of S = { S1, S2, .. , Sm} valued coins, how many ways can we
make the change? The order of coins doesn’t matter.
For example, for N = 4 and S = {1,2,3}, there are four solutions:
{1,1,1,1},{1,1,2},{2,2},{1,3}. So output should be 4. For N = 10 and S
= {2, 5, 3, 6}, there are five solutions: {2,2,2,2,2}, {2,2,3,3}, {2,2,6}, {2,3,5}
and {5,5}. So the output should be 5.
1) Optimal Substructure
To count total number solutions, we can divide all set solutions in two sets.
1) Solutions that do not contain mth coin (or Sm).
2) Solutions that contain at least one Sm.
Let count(S[], m, n) be the function to count the number of solutions, then it
can be written as sum of count(S[], m-1, n) and count(S[], m, n-Sm).
Therefore, the problem has optimal substructure property as the problem can
be solved using solutions to subproblems.
2) Overlapping Subproblems
Following is a simple recursive implementation of the Coin Change problem.
The implementation simply follows the recursive structure mentioned above.
#include<stdio.h>
// Returns the count of ways we can sum S[0...m-1] coins to get sum n
int count( int S[], int m, int n )
{
// If n is 0 then there is 1 solution (do not include any coin)
if (n == 0)
39
return 1;
It should be noted that the above function computes the same subproblems
again and again. See the following recursion tree for S = {1, 2, 3} and n = 5.
The function C({1}, 3) is called two times. If we draw the complete tree, then
we can see that there are many subproblems being called more than once.
40
/ \ / \ / \ / \
. . . . . . C({1}, 3) C({}, 4)
/ \
/ \
. .
Since same suproblems are called again, this problem has Overlapping Subpro-
lems property. So the Coin Change problem has both properties (see thisand
this) of a dynamic programming problem. Like other typical Dynamic Pro-
gramming(DP) problems, recomputations of same subproblems can be avoided
by constructing a temporary array table[][] in bottom up manner.
Dynamic Programming Solution
#include<stdio.h>
// total count
41
table[i][j] = x + y;
}
}
return table[n][m-1];
}
Python
# total count
table[i][j] = x + y
return table[n][m-1]
42
# Driver program to test above function
arr = [1, 2, 3]
m = len(arr)
n = 4
print(count(arr, m, n))
Output:
// Pick all coins one by one and update the table[] values
// after the index greater than or equal to the value of the
// picked coin
for(int i=0; i<m; i++)
for(int j=S[i]; j<=n; j++)
table[j] += table[j-S[i]];
return table[n];
}
43
Thanks to Rohan Laishram for suggesting this space optimized version.
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
References:
http://www.algorithmist.com/index.php/Coin_Change
Source
http://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/
44
Chapter 8
Given a sequence of matrices, find the most efficient way to multiply these
matrices together. The problem is not actually to perform the multiplications,
but merely to decide in which order to perform the multiplications.
We have many options to multiply a chain of matrices because matrix multiplica-
tion is associative. In other words, no matter how we parenthesize the product,
the result will be the same. For example, if we had four matrices A, B, C, and
D, we would have:
However, the order in which we parenthesize the product affects the number of
simple arithmetic operations needed to compute the product, or the efficiency.
For example, suppose A is a 10 × 30 matrix, B is a 30 × 5 matrix, and C is a
5 × 60 matrix. Then,
45
Given an array p[] which represents the chain of matrices such that the ith matrix
Ai is of dimension p[i-1] x p[i]. We need to write a function MatrixChainOrder()
that should return the minimum number of multiplications needed to multiply
the chain.
1) Optimal Substructure:
A simple solution is to place parenthesis at all possible places, calculate the cost
for each placement and return the minimum value. In a chain of matrices of size
n, we can place the first set of parenthesis in n-1 ways. For example, if the given
chain is of 4 matrices. let the chain be ABCD, then there are 3 way to place first
set of parenthesis: A(BCD), (AB)CD and (ABC)D. So when we place a set of
parenthesis, we divide the problem into subproblems of smaller size. Therefore,
the problem has optimal substructure property and can be easily solved using
recursion.
Minimum number of multiplication needed to multiply a chain of size n = Min-
imum of all n-1 placements (these placements create subproblems of smaller
size)
2) Overlapping Subproblems
Following is a recursive implementation that simply follows the above optimal
substructure property.
46
/* A naive recursive implementation that simply follows the above optimal
substructure property */
#include<stdio.h>
#include<limits.h>
getchar();
return 0;
}
47
Time complexity of the above naive recursive approach is exponential. It should
be noted that the above function computes the same subproblems again and
again. See the following recursion tree for a matrix chain of size 4. The function
MatrixChainOrder(p, 3, 4) is called two times. We can see that there are many
subproblems being called more than once.
Since same suproblems are called again, this problem has Overlapping Subpro-
lems property. So Matrix Chain Multiplication problem has both properties
(see thisand this) of a dynamic programming problem. Like other typical Dy-
namic Programming(DP) problems, recomputations of same subproblems can
be avoided by constructing a temporary array m[][] in bottom up manner.
Dynamic Programming Solution
Following is C/C++ implementation for Matrix Chain Multiplication problem
using Dynamic Programming.
/* For simplicity of the program, one extra row and one extra column are
allocated in m[][]. 0th row and 0th column of m[][] are not used */
int m[n][n];
int i, j, k, L, q;
48
the matrix A[i]A[i+1]...A[j] = A[i..j] where dimention of A[i] is
p[i-1] x p[i] */
// L is chain length.
for (L=2; L<n; L++)
{
for (i=1; i<=n-L+1; i++)
{
j = i+L-1;
m[i][j] = INT_MAX;
for (k=i; k<=j-1; k++)
{
// q = cost/scalar multiplications
q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];
if (q < m[i][j])
m[i][j] = q;
}
}
}
return m[1][n-1];
}
int main()
{
int arr[] = {1, 2, 3, 4};
int size = sizeof(arr)/sizeof(arr[0]);
getchar();
return 0;
}
Python
49
# See the Cormen book for details of the following algorithm
import sys
# L is chain length.
for L in range(2, n):
for i in range(1, n-L+1):
j = i+L-1
m[i][j] = sys.maxint
for k in range(i, j):
# q = cost/scalar multiplications
q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]
if q < m[i][j]:
m[i][j] = q
return m[1][n-1]
Output:
50
Auxiliary Space: O(nˆ2)
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
References:
http://en.wikipedia.org/wiki/Matrix_chain_multiplication
http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/
Dynamic/chainMatrixMult.htm
Source
http://www.geeksforgeeks.org/dynamic-programming-set-8-matrix-chain-multiplication/
51
Chapter 9
2) Overlapping Subproblems
Following is simple recursive implementation that simply follows the recursive
structure mentioned above.
52
// Returns value of Binomial Coefficient C(n, k)
int binomialCoeff(int n, int k)
{
// Base Cases
if (k==0 || k==n)
return 1;
// Recur
return binomialCoeff(n-1, k-1) + binomialCoeff(n-1, k);
}
It should be noted that the above function computes the same subproblems
again and again. See the following recursion tree for n = 5 an k = 2. The
function C(3, 1) is called two times. For large values of n, there will be many
common subproblems.
C(5, 2)
/ \
C(4, 1) C(4, 2)
/ \ / \
C(3, 0) C(3, 1) C(3, 1) C(3, 2)
/ \ / \ / \
C(2, 0) C(2, 1) C(2, 0) C(2, 1) C(2, 1) C(2, 2)
/ \ / \ / \
C(1, 0) C(1, 1) C(1, 0) C(1, 1) C(1, 0) C(1, 1)
Since same suproblems are called again, this problem has Overlapping Sub-
prolems property. So the Binomial Coefficient problem has both properties
(see thisand this) of a dynamic programming problem. Like other typical Dy-
namic Programming(DP) problems, recomputations of same subproblems can
be avoided by constructing a temporary array C[][] in bottom up manner. Fol-
lowing is Dynamic Programming based implementation.
53
C
return C[n][k];
}
54
}
Python
return C[n][k]
Output:
Value of C[5][2] is 10
55
Following is a space optimized version of the above code. The following code
only uses O(k). Thanks to AKfor suggesting this method.
C[0] = 1;
return res;
}
http://www.csl.mtu.edu/cs4321/www/Lectures/Lecture%2015%20-%20Dynamic%
20Programming%20Binomial%20Coefficients.htm
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/dynamic-programming-set-9-binomial-coefficient/
56
Chapter 10
Given weights and values of n items, put these items in a knapsack of capacity
W to get the maximum total value in the knapsack. In other words, given
two integer arrays val[0..n-1] and wt[0..n-1] which represent values and weights
associated with n items respectively. Also given an integer W which represents
knapsack capacity, find out the maximum value subset of val[] such that sum of
the weights of this subset is smaller than or equal to W. You cannot break an
item, either pick the complete item, or don’t pick it (0-1 property).
A simple solution is to consider all subsets of items and calculate the total weight
and value of all subsets. Consider the only subsets whose total weight is smaller
than W. From all such subsets, pick the maximum value subset.
1) Optimal Substructure:
To consider all subsets of items, there can be two cases for every item: (1) the
item is included in the optimal subset, (2) not included in the optimal set.
Therefore, the maximum value that can be obtained from n items is max of
following two values.
1) Maximum value obtained by n-1 items and W weight (excluding nth item).
2) Value of nth item plus maximum value obtained by n-1 items and W minus
weight of the nth item (including nth item).
If weight of nth item is greater than W, then the nth item cannot be included
and case 1 is the only possibility.
2) Overlapping Subproblems
Following is recursive implementation that simply follows the recursive structure
mentioned above.
57
/* A Naive recursive implementation of 0-1 Knapsack problem */
#include<stdio.h>
// Return the maximum of two cases: (1) nth item included (2) not included
else return max( val[n-1] + knapSack(W-wt[n-1], wt, val, n-1),
knapSack(W, wt, val, n-1)
);
}
It should be noted that the above function computes the same subproblems
again and again. See the following recursion tree, K(1, 1) is being evaluated
twice. Time complexity of this naive recursive solution is exponential (2ˆn).
58
wt[] = {1, 1, 1}, W = 2, val[] = {10, 20, 30}
Since suproblems are evaluated again, this problem has Overlapping Subpro-
lems property. So the 0-1 Knapsack problem has both properties (see thisand
this) of a dynamic programming problem. Like other typical Dynamic Pro-
gramming(DP) problems, recomputations of same subproblems can be avoided
by constructing a temporary array K[][] in bottom up manner. Following is
Dynamic Programming based implementation.
C++
59
K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]], K[i-1][w]);
else
K[i][w] = K[i-1][w];
}
}
return K[n][W];
}
int main()
{
int val[] = {60, 100, 120};
int wt[] = {10, 20, 30};
int W = 50;
int n = sizeof(val)/sizeof(val[0]);
printf("%d", knapSack(W, wt, val, n));
return 0;
}
Python
return K[n][W]
60
n = len(val)
print(knapSack(W, wt, val, n))
Output:
220
Time Complexity: O(nW) where n is the number of items and W is the capacity
of knapsack.
References:
http://www.es.ele.tue.nl/education/5MC10/Solutions/knapsack.pdf
http://www.cse.unl.edu/~goddard/Courses/CSCE310J/Lectures/Lecture8-DynamicProgramming.
pdf
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/dynamic-programming-set-10-0-1-knapsack-problem/
61
Chapter 11
62
recursively calculate the minimum number of droppings needed in worst case.
The floor which gives the minimum value in worst case is going to be part of
the solution.
In the following solutions, we return the minimum number of trails in worst case;
these solutions can be easily modified to print floor numbers of every trials also.
1) Optimal Substructure:
When we drop an egg from a floor x, there can be two cases (1) The egg breaks
(2) The egg doesn’t break.
1) If the egg breaks after dropping from xth floor, then we only need to check
for floors lower than x with remaining eggs; so the problem reduces to x-1 floors
and n-1 eggs
2) If the egg doesn’t break after dropping from the xth floor, then we only need
to check for floors higher than x; so the problem reduces to k-x floors and n
eggs.
Since we need to minimize the number of trials in worst case, we take the
maximum of two cases. We consider the max of above two cases for every floor
and choose the floor which yields minimum number of trials.
2) Overlapping Subproblems
Following is recursive implementation that simply follows the recursive structure
mentioned above.
# include <stdio.h>
# include <limits.h>
63
// one floor, one trial needed.
if (k == 1 || k == 0)
return k;
return min + 1;
}
Output:
Minimum number of trials in worst case with 2 eggs and 10 floors is 4
It should be noted that the above function computes the same subproblems
again and again. See the following partial recursion tree, E(2, 2) is being evalu-
ated twice. There will many repeated subproblems when you draw the complete
recursion tree even for small values of n and k.
64
E(2,4)
|
-------------------------------------
| | | |
| | | |
x=1/\ x=2/\ x=3/ \ x=4/ \
/ \ / \ .... ....
/ \ / \
E(1,0) E(2,3) E(1,1) E(2,2)
/\ /\... / \
x=1/ \ .....
/ \
E(1,0) E(2,2)
/ \
......
Since same suproblems are called again, this problem has Overlapping Subpro-
lems property. So Egg Dropping Puzzle has both properties (see thisand this)
of a dynamic programming problem. Like other typical Dynamic Program-
ming(DP) problems, recomputations of same subproblems can be avoided by
constructing a temporary array eggFloor[][] in bottom up manner.
Dynamic Programming Solution
Following are C++ and Python implementations for Egg Dropping problem
using Dynamic Programming.
C++
# A Dynamic Programming based C++ Program for the Egg Dropping Puzzle
# include <stdio.h>
# include <limits.h>
65
/* A 2D table where entery eggFloor[i][j] will represent minimum
number of trials needed for i eggs and j floors. */
int eggFloor[n+1][k+1];
int res;
int i, j, x;
// We need one trial for one floor and0 trials for 0 floors
for (i = 1; i <= n; i++)
{
eggFloor[i][1] = 1;
eggFloor[i][0] = 0;
}
66
Python
# A Dynamic Programming based Python Program for the Egg Dropping Puzzle
INT_MAX = 32767
# We need one trial for one floor and0 trials for 0 floors
for i in range(1, n+1):
eggFloor[i][1] = 1
eggFloor[i][0] = 0
67
Output:
Minimum number of trials in worst case with 2 eggs and 36 floors is 8
http://archive.ite.journal.informs.org/Vol4No1/Sniedovich/index.php
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/dynamic-programming-set-11-egg-dropping-puzzle/
68
Chapter 12
Set 12 (Longest
Palindromic Subsequence)
Given a sequence, find the length of the longest palindromic subsequence in it.
For example, if the given sequence is “BBABCBCAB”, then the output should
be 7 as “BABCBAB” is the longest palindromic subseuqnce in it. “BBBBB”
and “BBCBB” are also palindromic subsequences of the given sequence, but
not the longest ones.
The naive solution for this problem is to generate all subsequences of the given
sequence and find the longest palindromic subsequence. This solution is ex-
ponential in term of time complexity. Let us see how this problem possesses
both important properties of a Dynamic Programming (DP) Problem and can
efficiently solved using Dynamic Programming.
1) Optimal Substructure:
Let X[0..n-1] be the input sequence of length n and L(0, n-1) be the length of
the longest palindromic subsequence of X[0..n-1].
If last and first characters of X are same, then L(0, n-1) = L(1, n-2) + 2.
Else L(0, n-1) = MAX (L(1, n-1), L(0, n-2)).
Following is a general recursive solution with all cases handled.
69
Else if (j == i + 1) L(i, j) = 2
// If there are more than two characters, and first and last
// characters are same
Else L(i, j) = L(i + 1, j - 1) + 2
2) Overlapping Subproblems
Following is simple recursive implementation of the LPS problem. The imple-
mentation simply follows the recursive structure mentioned above.
#include<stdio.h>
#include<string.h>
// Base Case 2: If there are only 2 characters and both are same
if (seq[i] == seq[j] && i + 1 == j)
return 2;
70
return 0;
}
Output:
L(0, 5)
/ \
/ \
L(1,5) L(0,4)
/ \ / \
/ \ / \
L(2,5) L(1,4) L(1,4) L(0,3)
In the above partial recursion tree, L(1, 4) is being solved twice. If we draw the
complete recursion tree, then we can see that there are many subproblems which
are solved again and again. Since same suproblems are called again, this prob-
lem has Overlapping Subprolems property. So LPS problem has both properties
(see thisand this) of a dynamic programming problem. Like other typical Dy-
namic Programming(DP) problems, recomputations of same subproblems can
be avoided by constructing a temporary array L[][] in bottom up manner.
Dynamic Programming Solution
C++
71
// A utility function to get max of two integers
int max (int x, int y) { return (x > y)? x : y; }
// Build the table. Note that the lower diagonal values of table are
// useless and not filled in the process. The values are filled in a
// manner similar to Matrix Chain Multiplication DP solution (See
// http://www.geeksforgeeks.org/archives/15553). cl is length of
// substring
for (cl=2; cl<=n; cl++)
{
for (i=0; i<n-cl+1; i++)
{
j = i+cl-1;
if (str[i] == str[j] && cl == 2)
L[i][j] = 2;
else if (str[i] == str[j])
L[i][j] = L[i+1][j-1] + 2;
else
L[i][j] = max(L[i][j-1], L[i+1][j]);
}
}
return L[0][n-1];
}
72
Python
# Build the table. Note that the lower diagonal values of table are
# useless and not filled in the process. The values are filled in a
# manner similar to Matrix Chain Multiplication DP solution (See
# http://www.geeksforgeeks.org/dynamic-programming-set-8-matrix-chain-multiplication/
# cl is length of substring
for cl in range(2, n+1):
for i in range(n-cl+1):
j = i+cl-1
if str[i] == str[j] and cl == 2:
L[i][j] = 2
elif str[i] == str[j]:
L[i][j] = L[i+1][j-1] + 2
else:
L[i][j] = max(L[i][j-1], L[i+1][j]);
return L[0][n-1]
Output:
73
The lnegth of the LPS is 7
Source
http://www.geeksforgeeks.org/dynamic-programming-set-12-longest-palindromic-subsequence/
74
Chapter 13
Given a rod of length n inches and an array of prices that contains prices of
all pieces of size smaller than n. Determine the maximum value obtainable by
cutting up the rod and selling the pieces. For example, if length of the rod is
8 and the values of different pieces are given as following, then the maximum
obtainable value is 22 (by cutting in two pieces of lengths 2 and 6)
length | 1 2 3 4 5 6 7 8
--------------------------------------------
price | 1 5 8 9 10 17 17 20
And if the prices are as following, then the maximum obtainable value is 24 (by
cutting in eight pieces of length 1)
length | 1 2 3 4 5 6 7 8
--------------------------------------------
price | 3 5 8 9 10 17 17 20
The naive solution for this problem is to generate all configurations of different
pieces and find the highest priced configuration. This solution is exponential in
term of time complexity. Let us see how this problem possesses both important
properties of a Dynamic Programming (DP) Problem and can efficiently solved
using Dynamic Programming.
75
1) Optimal Substructure:
We can get the best price by making a cut at different positions and comparing
the values obtained after a cut. We can recursively call the same function for a
piece obtained after a cut.
Let cutRoad(n) be the required (best possible price) value for a rod of lenght n.
cutRod(n) can be written as following.
cutRod(n) = max(price[i] + cutRod(n-i-1)) for all i in {0, 1 .. n-1}
2) Overlapping Subproblems
Following is simple recursive implementation of the Rod Cutting problem. The
implementation simply follows the recursive structure mentioned above.
return max_val;
}
76
Output:
cR(4)
/ / \ \
/ / \ \
cR(3) cR(2) cR(1) cR(0)
/ | \ / \ |
/ | \ / \ |
cR(2) cR(1) cR(0) cR(1) cR(0) cR(0)
/ \ | |
/ \ | |
cR(1) cR(0) cR(0) cR(0)
In the above partial recursion tree, cR(2) is being solved twice. We can see
that there are many subproblems which are solved again and again. Since
same suproblems are called again, this problem has Overlapping Subprolems
property. So the Rod Cutting problem has both properties (see thisand this) of a
dynamic programming problem. Like other typical Dynamic Programming(DP)
problems, recomputations of same subproblems can be avoided by constructing
a temporary array val[] in bottom up manner.
C++
77
int max(int a, int b) { return (a > b)? a : b;}
// Build the table val[] in bottom up manner and return the last entry
// from the table
for (i = 1; i<=n; i++)
{
int max_val = INT_MIN;
for (j = 0; j < i; j++)
max_val = max(max_val, price[j] + val[i-j-1]);
val[i] = max_val;
}
return val[n];
}
Python
78
val[0] = 0
return val[n]
Output:
Source
http://www.geeksforgeeks.org/dynamic-programming-set-13-cutting-a-rod/
79
Chapter 14
80
int msis[n];
return max;
}
Python
81
for i in range(n):
msis[i] = arr[i]
return max
Output:
Source
http://www.geeksforgeeks.org/dynamic-programming-set-14-maximum-sum-increasing-subsequence/
82
Chapter 15
83
arrays lis[] and lds[] using Dynamic Programming solution of LIS problem. lis[i]
stores the length of the Longest Increasing subsequence ending with arr[i]. lds[i]
stores the length of the longest Decreasing subsequence starting from arr[i].
Finally, we need to return the max value of lis[i] + lds[i] – 1 where i is from 0
to n-1.
Following is C++ implementation of the above Dynamic Programming solution.
84
lds[i] = lds[j] + 1;
getchar();
return 0;
}
Output:
Length of LBS is 7
Source
http://www.geeksforgeeks.org/dynamic-programming-set-15-longest-bitonic-subsequence/
Category: Arrays Tags: Dynamic Programming
Post navigation
← Use of explicit keyword in C++ Set 16 (Floyd Warshall Algorithm) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
85
Chapter 16
The Floyd Warshall Algorithm is for solving the All Pairs Shortest Path problem.
The problem is to find shortest distances between every pair of vertices in a given
edge weighted directed Graph.
Example:
Input:
graph[][] = { {0, 5, INF, 10},
{INF, 0, 3, INF},
{INF, INF, 0, 1},
{INF, INF, INF, 0} }
which represents the following graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3
Note that the value of graph[i][j] is 0 if i is equal to j
And graph[i][j] is INF (infinite) if there is no edge from vertex i to j.
Output:
Shortest distance matrix
0 5 8 9
86
INF 0 3 4
INF INF 0 1
INF INF INF 0
C/C++
87
// A function to print the solution matrix
void printSolution(int dist[][V]);
// Solves the all-pairs shortest path problem using Floyd Warshall algorithm
void floydWarshell (int graph[][V])
{
/* dist[][] will be the output matrix that will finally have the shortest
distances between every pair of vertices */
int dist[V][V], i, j, k;
88
{
printf ("Following matrix shows the shortest distances"
" between every pair of vertices \n");
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
if (dist[i][j] == INF)
printf("%7s", "INF");
else
printf ("%7d", dist[i][j]);
}
printf("\n");
}
}
Java
89
// Path algorithm.
import java.util.*;
import java.lang.*;
import java.io.*;
class AllPairShortestPath
{
final static int INF = 99999, V = 4;
90
}
}
91
}
Output:
Following matrix shows the shortest distances between every pair of vertices
0 5 8 9
INF 0 3 4
INF INF 0 1
INF INF INF 0
#include<limits.h>
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above
Source
http://www.geeksforgeeks.org/dynamic-programming-set-16-floyd-warshall-algorithm/
92
Chapter 17
Set 17 (Palindrome
Partitioning)
// i is the starting index and j is the ending index. i must be passed as 0 and j as n-1
minPalPartion(str, i, j) = 0 if i == j. // When string is of length 1.
minPalPartion(str, i, j) = 0 if str[i..j] is palindrome.
93
Following is Dynamic Programming solution. It stores the solutions to subprob-
lems in two arrays P[][] and C[][], and reuses the calculated values.
94
// For substring of length L, set different possible starting indexes
for (i=0; i<n-L+1; i++)
{
j = i+L-1; // Set ending index
// Return the min cut value for complete string. i.e., str[0..n-1]
return C[0][n-1];
}
Output:
95
Time Complexity: O(n3 )
An optimization to above approach
In above approach, we can calculating minimum cut while finding all palin-
dromic substring. If we finding all palindromic substring 1st and then we calcu-
late minimum cut, time complexity will reduce to O(n2 ).
Thanks for Vivek for suggesting this optimization.
96
{
j = i+L-1; // Set ending index
// Return the min cut value for complete string. i.e., str[0..n-1]
return C[n-1];
}
Output:
97
Min cuts needed for Palindrome Partitioning is 3
Source
http://www.geeksforgeeks.org/dynamic-programming-set-17-palindrome-partitioning/
Category: Strings Tags: Dynamic Programming
Post navigation
← Operating Systems | Set 13 Operating Systems | Set 14 →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
98
Chapter 18
arr[] = {1, 5, 3}
Output: false
The array cannot be partitioned into equal sum sets.
99
there is a subset of arr[0..n-1] with sum equal to sum/2
100
// If sum is odd, there cannot be two subsets with equal sum
if (sum%2 != 0)
return false;
Output:
Time Complexity: O(2ˆn) In worst case, this solution tries two possibilities
(whether to include or exclude) for every element.
Dynamic Programming Solution
The problem can be solved using dynamic programming when the sum of the
elements is not too big. We can create a 2D array part[][] of size (sum/2)*(n+1).
And we can construct the solution in bottom up manner such that every filled
entry has following property
101
// A Dynamic Programming solution to partition problem
#include <stdio.h>
if (sum%2 != 0)
return false;
bool part[sum/2+1][n+1];
102
return part[sum/2][n];
}
Output:
Following diagram shows the values in partition table. The diagram is taken
form the wiki page of partition problem.
103
References:
http://en.wikipedia.org/wiki/Partition_problem
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/dynamic-programming-set-18-partition-problem/
Category: Arrays Tags: Dynamic Programming
Post navigation
← Automata Theory | Set 5 Database Management Systems | Set 11 →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
104
Chapter 19
Given a sequence of words, and a limit on the number of characters that can be
put in one line (line width). Put line breaks in the given sequence such that the
lines are printed neatly. Assume that the length of each word is smaller than
the line width.
The word processors like MS Word do task of placing line breaks. The idea is to
have balanced lines. In other words, not have few lines with lots of extra spaces
and some lines with small amount of extra spaces.
The extra spaces includes spaces put at the end of every line except the last one.
The problem is to minimize the following total cost.
Cost of a line = (Number of extra spaces in the line)^3
Total Cost = Sum of costs for all lines
The total extra spaces in line 1, line 2 and line 3 are 0, 2 and 3 respectively.
So optimal value of total cost is 0 + 2*2 + 3*3 = 13
105
Please note that the total cost function is not sum of extra spaces, but sum of
cubes (or square is also used) of extra spaces. The idea behind this cost function
is to balance the spaces among lines. For example, consider the following two
arrangement of same set of words:
1) There are 3 lines. One line has 3 extra spaces and all other lines have 0 extra
spaces. Total extra spaces = 3 + 0 + 0 = 3. Total cost = 3*3*3 + 0*0*0 +
0*0*0 = 27.
2) There are 3 lines. Each of the 3 lines has one extra space. Total extra spaces
= 1 + 1 + 1 = 3. Total cost = 1*1*1 + 1*1*1 + 1*1*1 = 3.
Total extra spaces are 3 in both scenarios, but second arrangement should be
preferred because extra spaces are balanced in all three lines. The cost function
with cubic sum serves the purpose because the value of total cost in second
scenario is less.
Method 1 (Greedy Solution)
The greedy solution is to place as many words as possible in the first line. Then
do the same thing for the second line and so on until all words are placed. This
solution gives optimal solution for many cases, but doesn’t give optimal solution
in all cases. For example, consider the following string “aaa bb cc ddddd” and
line width as 6. Greedy method will produce following output.
aaa bb
cc
ddddd
Extra spaces in the above 3 lines are 0, 4 and 1 respectively. So total cost is 0
+ 64 + 1 = 65.
But the above solution is not the best solution. Following arrangement has more
balanced spaces. Therefore less value of total cost function.
aaa
bb cc
ddddd
Extra spaces in the above 3 lines are 3, 1 and 1 respectively. So total cost is 27
+ 1 + 1 = 29.
Despite being sub-optimal in some cases, the greedy approach is used by many
word processors like MS Word and OpenOffice.org Writer.
106
Method 2 (Dynamic Programming)
The following Dynamic approach strictly follows the algorithm given in solution
of Cormen book. First we compute costs of all possible lines in a 2D table lc[][].
The value lc[i][j] indicates the cost to put words from i to j in a single line where
i and j are indexes of words in the input sequences. If a sequence of words from
i to j cannot fit in a single line, then lc[i][j] is considered infinite (to avoid it
from being a part of the solution). Once we have the lc[][] table constructed,
we can calculate total cost using following recursive formula. In the following
formula, C[j] is the optimized total cost for arranging words from 1 to j.
The above recursion has overlapping subproblem property. For example, the
solution of subproblem c(2) is used by c(3), C(4) and so on. So Dynamic
Programming is used to store the results of subproblems. The array c[] can be
computed from left to right, since each value depends only on earlier values.
To print the output, we keep track of what words go on what lines, we can keep
a parallel p array that points to where each c value came from. The last line
starts at word p[n] and goes through word n. The previous line starts at word
p[p[n]] and goes through word p[n?] – 1, etc. The function printSolution() uses
p[] to print the solution.
In the below program, input is an array l[] that represents lengths of words in
a sequence. The value l[i] indicates length of the ith word (i starts from 1) in
theinput sequence.
107
// extras[i][j] will have number of extra spaces if words from i
// to j are put in a single line
int extras[n+1][n+1];
int i, j;
108
// from word number 1 to j.
c[0] = 0;
for (j = 1; j <= n; j++)
{
c[j] = INF;
for (i = 1; i <= j; i++)
{
if (c[i-1] != INF && lc[i][j] != INF && (c[i-1] + lc[i][j] < c[j]))
{
c[j] = c[i-1] + lc[i][j];
p[j] = i;
}
}
}
printSolution(p, n);
}
Output:
109
Line number 3: From word no. 4 to 4
Source
http://www.geeksforgeeks.org/dynamic-programming-set-18-word-wrap/
110
Chapter 20
You are given n pairs of numbers. In every pair, the first number is always
smaller than the second number. A pair (c, d) can follow another pair (a, b) if
b Amazon Interview | Set 2
For example, if the given pairs are {{5, 24}, {39, 60}, {15, 28}, {27, 40}, {50,
90} }, then the longest chain that can be formed is of length 3, and the chain
is {{5, 24}, {27, 40}, {50, 90}}
This problem is a variation of standard Longest Increasing Subsequence problem.
Following is a simple two step process.
1) Sort given pairs in increasing order of first (or smaller) element.
2) Now run a modified LIS process where we compare the second element of
already finalized LIS with the first element of new LIS being constructed.
The following code is a slight modification of method 2 of this post.
#include<stdio.h>
#include<stdlib.h>
111
// according the first (or smaller) values in pairs.
int maxChainLength( struct pair arr[], int n)
{
int i, j, max = 0;
int *mcl = (int*) malloc ( sizeof( int ) * n );
// mcl[i] now stores the maximum chain length ending with pair i
return max;
}
Output:
112
Time Complexity: O(nˆ2) where n is the number of pairs.
The given problem is also a variation of Activity Selection problemand can be
solved in (nLogn) time. To solve it as a activity selection problem, consider the
first element of a pair as start time in activity selection problem, and the second
element of pair as end time. Thanks to Palash for suggesting this approach.
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/dynamic-programming-set-20-maximum-length-chain-of-pairs/
113
Chapter 21
8 1 4 3 5 2 6 7
--------------------------------------------
--------------------------------------------
1 2 3 4 5 6 7 8
Source:Dynamic Programming Practice Problems. The link also has well ex-
plained solution for the problem.
2. Maximum Sum Increasing Subsequence: Given an array of n positive
integers. Write a program to find the maximum sum subsequence of the given
array such that the intgers in the subsequence are sorted in increasing order.
For example, if input is {1, 101, 2, 3, 100, 4, 5}, then output should be {1, 2, 3,
100}. The solution to this problem has been published here.
114
3. The Longest Chain You are given pairs of numbers. In a pair, the first
number is smaller with respect to the second number. Suppose you have two
sets (a, b) and (c, d), the second set can follow the first set if b here.
4. Box Stacking You are given a set of n types of rectangular 3-D boxes,
where the iˆth box has height h(i), width w(i) and depth d(i) (all real numbers).
You want to create a stack of boxes which is as tall as possible, but you can
only stack a box on top of another box if the dimensions of the 2-D base of the
lower box are each strictly larger than those of the 2-D base of the higher box.
Of course, you can rotate a box so that any side functions as its base. It is also
allowable to use multiple instances of the same type of box.
Source:Dynamic Programming Practice Problems. The link also has well ex-
plained solution for the problem.
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/dynamic-programming-set-14-variations-of-lis/
115
Chapter 22
You are given a set of n types of rectangular 3-D boxes, where the iˆth box has
height h(i), width w(i) and depth d(i) (all real numbers). You want to create
a stack of boxes which is as tall as possible, but you can only stack a box on
top of another box if the dimensions of the 2-D base of the lower box are each
strictly larger than those of the 2-D base of the higher box. Of course, you can
rotate a box so that any side functions as its base. It is also allowable to use
multiple instances of the same type of box.
Source: http://people.csail.mit.edu/bdean/6.046/dp/. The link also has video
for explanation of solution.
116
The Box Stacking problem is a variation of LIS problem. We need to build a
maximum height stack.
Following are the key points to note in the problem statement:
1) A box can be placed on top of another box only if both width and depth
of the upper placed box are smaller than width and depth of the lower box
respectively.
2) We can rotate boxes. For example, if there is a box with dimensions {1x2x3}
where 1 is height, 2×3 is base, then there can be three possibilities, {1x2x3},
{2x1x3} and {3x1x2}.
3) We can use multiple instances of boxes. What it means is, we can have two
different rotations of a box as part of our maximum height stack.
Following is the solution based on DP solution of LIS problem.
1) Generate all 3 rotations of all boxes. The size of rotation array becomes
3 times the size of original array. For simplicity, we consider depth as always
smaller than or equal to width.
2) Sort the above generated 3n boxes in decreasing order of base area.
3) After sorting the boxes, the problem is same as LIS with following optimal
substructure property.
MSH(i) = Maximum possible Stack Height with box i at top of stack
MSH(i) = { Max ( MSH(j) ) + height(i) } where j width(i) and depth(j) >
117
depth(i).
If there is no such j then MSH(i) = height(i)
4) To get overall maximum height, we return max(MSH(i)) where 0 /* Dynamic
Programming implementation of Box Stacking problem */ #include<stdio.h>
#include<stdlib.h> /* Representation of a box */ struct Box { // h –> height,
w –> width, d –> depth int h, w, d; // for simplicity of solution, always keep
w <= d }; // A utility function to get minimum of two intgers int min (int
x, int y) { return (x < y)? x : y; } // A utility function to get maximum
of two intgers int max (int x, int y) { return (x > y)? x : y; } /* Following
function is needed for library function qsort(). We use qsort() to sort boxes in
decreasing order of base area. Refer following link for help of qsort() and com-
pare() http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/ */ int com-
pare (const void *a, const void * b) { return ( (*(Box *)b).d * (*(Box *)b).w )
– ( (*(Box *)a).d * (*(Box *)a).w ); } /* Returns the height of the tallest stack
that can be formed with give type of boxes */ int maxStackHeight( Box arr[], int
n ) { /* Create an array of all rotations of given boxes For example, for a box {1,
2, 3}, we consider three instances{{1, 2, 3}, {2, 1, 3}, {3, 1, 2}} */ Box rot[3*n];
int index = 0; for (int i = 0; i < n; i++) { // Copy the original box rot[index]
= arr[i]; index++; // First rotation of box rot[index].h = arr[i].w; rot[index].d
= max(arr[i].h, arr[i].d); rot[index].w = min(arr[i].h, arr[i].d); index++; // Sec-
ond rotation of box rot[index].h = arr[i].d; rot[index].d = max(arr[i].h, arr[i].w);
rot[index].w = min(arr[i].h, arr[i].w); index++; } // Now the number of boxes
is 3n n = 3*n; /* Sort the array ‘rot[]’ in decreasing order, using library function
for quick sort */ qsort (rot, n, sizeof(rot[0]), compare); // Uncomment following
two lines to print all rotations // for (int i = 0; i < n; i++ ) // printf(“%d x
%d x %d\n”, rot[i].h, rot[i].w, rot[i].d); /* Initialize msh values for all indexes
msh[i] –> Maximum possible Stack Height with box i on top */ int msh[n]; for
(int i = 0; i < n; i++ ) msh[i] = rot[i].h; /* Compute optimized msh values in
bottom up manner */ for (int i = 1; i < n; i++ ) for (int j = 0; j < i; j++ ) if (
rot[i].w < rot[j].w && rot[i].d < rot[j].d && msh[i] < msh[j] + rot[i].h ) { msh[i]
= msh[j] + rot[i].h; } /* Pick maximum of all msh values */ int max = -1; for
( int i = 0; i < n; i++ ) if ( max < msh[i] ) max = msh[i]; return max; } /*
Driver program to test above function */ int main() { Box arr[] = { {4, 6, 7},
{1, 2, 3}, {4, 5, 6}, {10, 12, 32} }; int n = sizeof(arr)/sizeof(arr[0]); printf(“The
maximum possible height of stack is %d\n”, maxStackHeight (arr, n) ); return
0; }
Output:
In the above program, given input boxes are {4, 6, 7}, {1, 2, 3}, {4, 5, 6}, {10,
12, 32}. Following are all rotations of the boxes in decreasing order of base area.
118
10 x 12 x 32
12 x 10 x 32
32 x 10 x 12
4 x 6 x 7
4 x 5 x 6
6 x 4 x 7
5 x 4 x 6
7 x 4 x 6
6 x 4 x 5
1 x 2 x 3
2 x 1 x 3
3 x 1 x 2
The height 60 is obtained by boxes { {3, 1, 2}, {1, 2, 3}, {6, 4, 5}, {4, 5, 6},
{4, 6, 7}, {32, 10, 12}, {10, 12, 32}}
Time Complexity: O(nˆ2)
Auxiliary Space: O(n)
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/dynamic-programming-set-21-box-stacking-problem/
119
Chapter 23
Set 23 (Bellman–Ford
Algorithm)
Given a graph and a source vertex src in graph, find shortest paths from src to
all vertices in the given graph. The graph may contain negative weight edges.
We have discussed Dijkstra’s algorithm for this problem. Dijksra’s algorithm is a
Greedy algorithm and time complexity is O(VLogV) (with the use of Fibonacci
heap). Dijkstra doesn’t work for Graphs with negative weight edges, Bellman-
Ford works for such graphs. Bellman-Ford is also simpler than Dijkstra and
suites well for distributed systems. But time complexity of Bellman-Ford is
O(VE), which is more than Dijkstra.
Algorithm
Following are the detailed steps.
Input: Graph and a source vertex src
Output: Shortest distance to all vertices from src. If there is a negative weight
cycle, then shortest distances are not calculated, negative weight cycle is re-
ported.
1) This step initializes distances from source to all vertices as infinite and dis-
tance to source itself as 0. Create an array dist[] of size |V| with all values as
infinite except dist[src] where src is source vertex.
2) This step calculates shortest distances. Do following |V|-1 times where |V|
is the number of vertices in given graph.
…..a) Do following for each edge u-v
………………If dist[v] > dist[u] + weight of edge uv, then update dist[v]
………………….dist[v] = dist[u] + weight of edge uv
3) This step reports if there is a negative weight cycle in graph. Do following
for each edge u-v
120
……If dist[v] > dist[u] + weight of edge uv, then “Graph contains negative weight
cycle”
The idea of step 3 is, step 2 guarantees shortest distances if graph doesn’t contain
negative weight cycle. If we iterate through all edges one more time and get a
shorter path for any vertex, then there is a negative weight cycle
How does this work? Like other Dynamic Programming Problems, the al-
gorithm calculate shortest paths in bottom-up manner. It first calculates the
shortest distances for the shortest paths which have at-most one edge in the
path. Then, it calculates shortest paths with at-nost 2 edges, and so on. Af-
ter the ith iteration of outer loop, the shortest paths with at most i edges are
calculated. There can be maximum |V| – 1 edges in any simple path, that is
why the outer loop runs |v| – 1 times. The idea is, assuming that there is no
negative weight cycle, if we have calculated shortest paths with at most i edges,
then an iteration over all edges guarantees to give shortest path with at-most
(i+1) edges (Proof is simple, you can refer this or MIT Video Lecture)
Example
Let us understand the algorithm with following example graph. The images are
taken from thissource.
Let the given source vertex be 0. Initialize all distances as infinite, except the
distance to source itself. Total number of vertices in the graph is 5, so all edges
must be processed 4 times.
Let all edges are processed in following order: (B,E), (D,B), (B,D), (A,B),
(A,C), (D,C), (B,C), (E,D). We get following distances when all edges are
processed first time. The first row in shows initial distances. The second row
shows distances when edges (B,E), (D,B), (B,D) and (A,B) are processed. The
third row shows distances when (A,C) is processed. The fourth row shows
when (D,C), (B,C) and (E,D) are processed.
121
The first iteration guarantees to give all shortest paths which are at most 1 edge
long. We get following distances when all edges are processed second time (The
last row shows final values).
The second iteration guarantees to give all shortest paths which are at most 2
edges long. The algorithm processes all edges 2 more times. The distances are
minimized after the second iteration, so third and fourth iterations don’t update
the distances.
Implementation:
C++
#include <stdio.h>
122
#include <stdlib.h>
#include <string.h>
#include <limits.h>
graph->edge =
(struct Edge*) malloc( graph->E * sizeof( struct Edge ) );
return graph;
}
123
void BellmanFord(struct Graph* graph, int src)
{
int V = graph->V;
int E = graph->E;
int dist[V];
printArr(dist, V);
return;
}
124
int main()
{
/* Let us create the graph given in above example */
int V = 5; // Number of vertices in graph
int E = 8; // Number of edges in graph
struct Graph* graph = createGraph(V, E);
125
BellmanFord(graph, 0);
return 0;
}
Java
int V, E;
Edge edge[];
126
{
int V = graph.V, E = graph.E;
int dist[] = new int[V];
127
for (int i=0; i<V; ++i)
System.out.println(i+"\t\t"+dist[i]);
}
128
// add edge 4-3 (or E-D in above figure)
graph.edge[7].src = 4;
graph.edge[7].dest = 3;
graph.edge[7].weight = -3;
graph.BellmanFord(graph, 0);
}
}
// Contributed by Aakash Hasija
Output:
Notes
1) Negative weights are found in various applications of graphs. For example,
instead of paying cost for a path, we may get some advantage if we follow the
path.
2) Bellman-Ford works better (better than Dijksra’s) for distributed systems.
Unlike Dijksra’s where we need to find minimum value of all vertices, in Bellman-
Ford, edges are considered one by one.
Exercise
1) The standard Bellman-Ford algorithm reports shortest path only if there is
no negative weight cycles. Modify it so that it reports minimum distances even
if there is a negative weight cycle.
2) Can we use Dijksra’s algorithm for shortest paths for graphs with negative
weights – one idea can be, calculate the minimum weight value, add a positive
value (equal to absolute value of minimum weight value) to all weights and run
the Dijksra’s algorithm for the modified graph. Will this algorithm work?
References:
http://www.youtube.com/watch?v=Ttezuzs39nk
http://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm
http://www.cs.arizona.edu/classes/cs445/spring07/ShortestPath2.prn.pdf
129
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/dynamic-programming-set-23-bellman-ford-algorithm/
130
Chapter 24
Given a sorted array keys[0.. n-1] of search keys and an array freq[0.. n-1] of
frequency counts, where freq[i] is the number of searches to keys[i]. Construct
a binary search tree of all keys such that the total cost of all the searches is as
small as possible.
Let us first define the cost of a BST. The cost of a BST node is level of that
node multiplied by its frequency. Level of root is 1.
Example 1
Input: keys[] = {10, 12}, freq[] = {34, 50}
There can be following two possible BSTs
10 12
\ /
12 10
I II
Frequency of searches of 10 and 12 are 34 and 50 respectively.
The cost of tree I is 34*1 + 50*2 = 134
The cost of tree II is 50*1 + 34*2 = 118
Example 2
Input: keys[] = {10, 12, 20}, freq[] = {34, 8, 50}
There can be following possible BSTs
10 12 20 10 20
\ / \ / \ /
12 10 20 12 20 10
\ / / \
131
20 10 12 12
I II III IV V
Among all possible BSTs, cost of the fifth BST is minimum.
Cost of the fifth BST is 1*50 + 2*34 + 3*8 = 142
1) Optimal Substructure:
The optimal cost for freq[i..j] can be recursively calculated using following
formula.
132
// Initialize minimum value
int min = INT_MAX;
// One by one consider all elements as root and recursively find cost
// of the BST, compare the cost with min and update min if needed
for (int r = i; r <= j; ++r)
{
int cost = optCost(freq, i, r-1) + optCost(freq, r+1, j);
if (cost < min)
min = cost;
}
// The main function that calculates minimum cost of a Binary Search Tree.
// It mainly uses optCost() to find the optimal cost.
int optimalSearchTree(int keys[], int freq[], int n)
{
// Here array keys[] is assumed to be sorted in increasing order.
// If keys[] is not sorted, then add code to sort keys, and rearrange
// freq[] accordingly.
return optCost(freq, 0, n-1);
}
133
Output:
Since same suproblems are called again, this problem has Overlapping Subpro-
lems property. So optimal BST problem has both properties (see thisand this)
of a dynamic programming problem. Like other typical Dynamic Program-
ming(DP) problems, recomputations of same subproblems can be avoided by
constructing a temporary array cost[][] in bottom up manner.
Dynamic Programming Solution
Following is C/C++ implementation for optimal BST problem using Dynamic
Programming. We use an auxiliary array cost[n][n] to store the solutions of
subproblems. cost[0][n-1] will hold the final result. The challenge in implemen-
tation is, all diagonal values must be filled first, then the values which lie on
the line just above the diagonal. In other words, we must first fill all cost[i][i]
values, then all cost[i][i+1] values, then all cost[i][i+2] values. So how to fill
the 2D array in such manner> The idea used in the implementation is same as
Matrix Chain Multiplication problem, we use a variable ‘L’ for chain length and
increment ‘L’, one by one. We calculate column number ‘j’ using the values of
‘i’ and ‘L’.
134
// A utility function to get sum of array elements freq[i] to freq[j]
int sum(int freq[], int i, int j);
135
int sum(int freq[], int i, int j)
{
int s = 0;
for (int k = i; k <=j; k++)
s += freq[k];
return s;
}
Output:
Notes
1) The time complexity of the above solution is O(nˆ4). The time complexity
can be easily reduced to O(nˆ3) by pre-calculating sum of frequencies instead
of calling sum() again and again.
2) In the above solutions, we have computed optimal cost only. The solutions
can be easily modified to store the structure of BSTs also. We can create another
auxiliary array of size n to store the structure of tree. All we need to do is, store
the chosen ‘r’ in the innermost loop.
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/dynamic-programming-set-24-optimal-binary-search-tree/
Category: Misc Tags: Dynamic Programming
Post navigation
← Strand Life Sciences Interview | Set 1 Facebook Interview | Set 1 →
136
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
137
Chapter 25
Let isSubSetSum(int set[], int n, int sum) be the function to find whether there
is a subset of set[] with sum equal to sum. n is the number of elements in set[].
The isSubsetSum problem can be divided into two subproblems
…a) Include the last element, recur for n = n-1, sum = sum – set[n-1]
…b) Exclude the last element, recur for n = n-1.
If any of the above the above subproblems return true, then return true.
Following is the recursive formula for isSubsetSum() problem.
138
Following is naive recursive implementation that simply follows the recursive
structure mentioned above.
// Returns true if there is a subset of set[] with sun equal to given sum
bool isSubsetSum(int set[], int n, int sum)
{
// Base Cases
if (sum == 0)
return true;
if (n == 0 && sum != 0)
return false;
Output:
139
The above solution may try all subsets of given set in worst case. Therefore
time complexity of the above solution is exponential. The problem is in-fact
NP-Complete (There is no known polynomial time solution for this problem).
We can solve the problem in Pseudo-polynomial time using Dynamic
programming. We create a boolean 2D table subset[][] and fill it in bottom
up manner. The value of subset[i][j] will be true if there is a subset of set[0..j-1]
with sum equal to i., otherwise false. Finally, we return subset[sum][n]
// Returns true if there is a subset of set[] with sun equal to given sum
bool isSubsetSum(int set[], int n, int sum)
{
// The value of subset[i][j] will be true if there is a subset of set[0..j-1]
// with sum equal to i
bool subset[sum+1][n+1];
140
return subset[sum][n];
}
Output:
Source
http://www.geeksforgeeks.org/dynamic-programming-subset-sum-problem/
Category: Misc Tags: Dynamic Programming
Post navigation
← Nvidia Interview | Set 1 Measure one litre using two vessels and infinite water
supply →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
141
Chapter 26
Set 26 (Largest
Independent Set Problem)
Given a Binary Tree, find size of the Largest Independent Set(LIS) in it. A
subset of all tree nodes is an independent set if there is no edge between any
two nodes of the subset.
For example, consider the following binary tree. The largest independent
set(LIS) is {10, 40, 60, 70, 80} and size of the LIS is 5.
142
A Dynamic Programming solution solves a given problem using solutions of
subproblems in bottom up manner. Can the given problem be solved using
solutions to subproblems? If yes, then what are the subproblems? Can we
find largest independent set size (LISS) for a node X if we know LISS for all
descendants of X? If a node is considered as part of LIS, then its children cannot
be part of LIS, but its grandchildren can be. Following is optimal substructure
property.
1) Optimal Substructure:
Let LISS(X) indicates size of largest independent set of a tree with root X.
The idea is simple, there are two possibilities for every node X, either X is a
member of the set or not a member. If X is a member, then the value of LISS(X)
is 1 plus LISS of all grandchildren. If X is not a member, then the value is sum
of LISS of all children.
2) Overlapping Subproblems
Following is recursive implementation that simply follows the recursive structure
mentioned above.
/* A binary tree node has data, pointer to left child and a pointer to
right child */
struct node
{
int data;
struct node *left, *right;
};
143
if (root == NULL)
return 0;
return 0;
}
144
Output:
/* A binary tree node has data, pointer to left child and a pointer to
right child */
struct node
{
int data;
int liss;
struct node *left, *right;
};
if (root->liss)
return root->liss;
145
if (root->left == NULL && root->right == NULL)
return (root->liss = 1);
return root->liss;
}
return 0;
146
}
Output
Time Complexity: O(n) where n is the number of nodes in given Binary tree.
Following extensions to above solution can be tried as an exercise.
1) Extend the above solution for n-ary tree.
2) The above solution modifies the given tree structure by adding an additional
field ‘liss’ to tree nodes. Extend the solution so that it doesn’t modify the tree
structure.
3) The above solution only returns size of LIS, it doesn’t print elements of LIS.
Extend the solution to print all nodes that are part of LIS.
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/largest-independent-set-problem/
147
Chapter 27
Given a 2D array, find the maximum sum subarray in it. For example, in
the following 2D array, the maximum sum subarray is highlighted with blue
rectangle and sum of this subarray is 29.
This problem is mainly an extension of Largest Sum Contiguous Subarray for
1D array.
The naive solution for this problem is to check every possible rectangle in
given 2D array. This solution requires 4 nested loops and time complexity of
this solution would be O(nˆ4).
Kadane’s algorithm for 1D array can be used to reduce the time complexity
to O(nˆ3). The idea is to fix the left and right columns one by one and find the
maximum sum contiguous rows for every left and right column pair. We basically
find top and bottom row numbers (which have maximum sum) for every fixed
left and right column pair. To find the top and bottom row numbers, calculate
sun of elements in every row from left to right and store these sums in an array
say temp[]. So temp[i] indicates sum of elements from left to right in row i. If we
apply Kadane’s 1D algorithm on temp[], and get the maximum sum subarray
of temp, this maximum sum would be the maximum possible sum with left and
right as boundary columns. To get the overall maximum sum, we compare this
sum with the maximum sum so far.
148
#define ROW 4
#define COL 5
// Just some initial value to check for all negative values case
*finish = -1;
// local variable
int local_start = 0;
149
maxSum = arr[i];
*start = *finish = i;
}
}
return maxSum;
}
// Set the right column for the left column set by outer loop
for (right = left; right < COL; ++right)
{
// Calculate sum between current left and right for every row 'i'
for (i = 0; i < ROW; ++i)
temp[i] += M[i][right];
// Compare sum with maximum sum so far. If sum is more, then update
// maxSum and other output values
if (sum > maxSum)
{
maxSum = sum;
finalLeft = left;
finalRight = right;
finalTop = start;
finalBottom = finish;
}
}
150
}
findMaxSum(M);
return 0;
}
Output:
Source
http://www.geeksforgeeks.org/dynamic-programming-set-27-max-sum-rectangle-in-a-2d-matrix/
Category: Arrays Tags: Dynamic Programming
Post navigation
← D E Shaw Interview | Set 1 [TopTalent.in] In Conversation With Nithin On
What It Takes To Get Into Goldman Sachs →
151
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
152
Chapter 28
153
// A utility function to find minimum of two numbers
int min(int a, int b)
{ return a < b ? a : b; }
// Check if the first and last characters are same. On the basis of the
// comparison result, decide which subrpoblem(s) to call
return (str[l] == str[h])? findMinInsertions(str, l + 1, h - 1):
(min(findMinInsertions(str, l, h - 1),
findMinInsertions(str, l + 1, h)) + 1);
}
Output:
abcde
/ | \
/ | \
bcde abcd bcd <- case 3 is discarded as str[l] != str[h]
/ | \ / | \
154
/ | \ / | \
cde bcd cd bcd abc bc
/ | \ / | \ /|\ / | \
de cd d cd bc c………………….
The substrings in bold show that the recursion to be terminated and the re-
cursion tree cannot originate from there. Substring in the same color indicates
overlapping subproblems.
How to reuse solutions of subproblems?
We can create a table to store results of subproblems so that they can be used
directly if same subproblem is encountered again.
The below table represents the stored values for the string abcde.
a b c d e
----------
0 1 2 3 4
0 0 1 2 3
0 0 0 1 2
0 0 0 0 1
0 0 0 0 0
Gap = 1:
(0, 1) (1, 2) (2, 3) (3, 4)
Gap = 2:
(0, 2) (1, 3) (2, 4)
Gap = 3:
(0, 3) (1, 4)
Gap = 4:
(0, 4)
155
// insertions needed to make a string palindrome
#include <stdio.h>
#include <string.h>
Output:
156
Another Dynamic Programming Solution (Variation of Longest Com-
mon Subsequence Problem)
The problem of finding minimum insertions can also be solved using Longest
Common Subsequence (LCS) Problem. If we find out LCS of string and its
reverse, we know how many maximum characters can form a palindrome. We
need insert remaining characters. Following are the steps.
1) Find the length of LCS of input string and its reverse. Let the length be ‘l’.
2) The minimum number insertions needed is length of input string minus ‘l’.
else
L[i][j] = max(L[i-1][j], L[i][j-1]);
}
}
157
// LCS based function to find minimum number of insersions
int findMinInsertionsLCS(char str[], int n)
{
// Creata another string to store reverse of 'str'
char rev[n+1];
strcpy(rev, str);
strrev(rev);
Output:
Time complexity of this method is also O(nˆ2) and this method also requires
O(nˆ2) extra space.
This article is compiled by Aashish Barnwal. Please write comments if you
find anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/dynamic-programming-set-28-minimum-insertions-to-form-a-palindrome/
Category: Misc Tags: Dynamic Programming
Post navigation
← Longest prefix matching – A Trie based solution in Java Set 29 (Longest
Common Substring) →
158
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
159
Chapter 29
Given two strings ‘X’ and ‘Y’, find the length of the longest common substring.
For example, if the given strings are “GeeksforGeeks” and “GeeksQuiz”, the
output should be 5 as longest common substring is “Geeks”
Let m and n be the lengths of first and second strings respectively.
A simple solution is to one by one consider all substrings of first string and
for every substring check if it is a substring in second string. Keep track of the
maximum length substring. There will be O(mˆ2) substrings and we can find
whether a string is subsring on another string in O(n) time (See this). So overall
time complexity of this method would be O(n * m2 )
Dynamic Programming can be used to find the longest common substring
in O(m*n) time. The idea is to find length of the longest common suffix for all
substrings of both strings and store these lengths in a table.
The maximum length Longest Common Suffix is the longest common substring.
LCSubStr(X, Y, m, n) = Max(LCSuff(X, Y, i, j)) where 1
Following is C++ implementation of the above solution.
160
using namespace std;
int m = strlen(X);
int n = strlen(Y);
cout << "Length of Longest Common Substring is " << LCSubStr(X, Y, m, n);
161
return 0;
}
Output:
Source
http://www.geeksforgeeks.org/longest-common-substring/
Category: Strings Tags: Dynamic Programming
162
Chapter 30
Given n dice each with m faces, numbered from 1 to m, find the number of ways
to get sum X. X is the summation of values on each face when all the dice are
thrown.
The Naive approach is to find all the possible combinations of values from n
dice and keep on counting the results that sum to X.
This problem can be efficiently solved using Dynamic Programming (DP).
Why DP approach?
The above problem exhibits overlapping subproblems. See the below diagram.
Also, see thisrecursive implementation. Let there be 3 dice, each with 6 faces
and we need to find the number of ways to get sum 8:
163
Sum(6, 3, 8) = Sum(6, 2, 7) + Sum(6, 2, 6) + Sum(6, 2, 5) +
Sum(6, 2, 4) + Sum(6, 2, 3) + Sum(6, 2, 2)
Please take a closer look at the above recursion. The sub-problems in RED are
solved first time and sub-problems in BLUE are solved again (exhibit overlap-
ping sub-problems). Hence, storing the results of the solved sub-problems saves
time.
Following is C++ implementation of Dynamic Programming approach.
// C++ program to find number of ways to get sum 'x' with 'n'
// dice where every dice has 'm' faces
#include <iostream>
#include <string.h>
using namespace std;
// The main function that returns number of ways to get sum 'x'
// with 'n' dice and 'm' with m faces.
int findWays(int m, int n, int x)
164
{
// Create a table to store results of subproblems. One extra
// row and column are used for simpilicity (Number of dice
// is directly used as row index and sum is directly used
// as column index). The entries in 0th row and 0th column
// are never used.
int table[n + 1][x + 1];
memset(table, 0, sizeof(table)); // Initialize all entries as 0
return 0;
}
Output:
165
0
2
21
4
6
With above conditions added, time complexity becomes O(1) when x >= m*n
or when x Exercise:
Extend the above algorithm to find the probability to get Sum > X.
This article is compiled by Aashish Barnwal. Please write comments if you
find anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/dice-throw-problem/
Category: Misc Tags: Dynamic Programming
Post navigation
← Biconnected graph [TopTalent.in] Interview With Nandini from VNIT Who
Bagged an Off Campus Job in Microsoft →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
166
Chapter 31
167
So if the user follows the second game state, maximum value can be collected
although the first move is not the best.
There are two choices:
1. The user chooses the ith coin with value Vi: The opponent either chooses
(i+1)th coin or jth coin. The opponent intends to choose the coin which leaves
the user with minimum value.
i.e. The user can collect the value Vi + min(F(i+2, j), F(i+1, j-1) )
2. The user chooses the jth coin with value Vj: The opponent either chooses
ith coin or (j-1)th coin. The opponent intends to choose the coin which leaves
the user with minimum value.
i.e. The user can collect the value Vj + min(F(i+1, j-1), F(i, j-2) )
Following is recursive solution that is based on above two choices. We take the
maximum of two choices.
168
F(i, j) represents the maximum value the user can collect from
i'th coin to j'th coin.
// Fill table using above recursive formula. Note that the table
// is filled in diagonal fashion (similar to http://goo.gl/PQqoS),
// from diagonal elements to table[0][n-1] which is the result.
for (gap = 0; gap < n; ++gap)
{
for (i = 0, j = gap; j < n; ++i, ++j)
{
// Here x is value of F(i+2, j), y is F(i+1, j-1) and
// z is F(i, j-2) in above recursive formula
x = ((i+2) <= j) ? table[i+2][j] : 0;
y = ((i+1) <= (j-1)) ? table[i+1][j-1] : 0;
z = (i <= (j-2))? table[i][j-2]: 0;
169
}
return table[0][n-1];
}
return 0;
}
Output:
22
4
42
Exercise
Your thoughts on the strategy when the user wishes to only win instead of
winning with the maximum value. Like above problem, number of coins is even.
Can Greedy approach work quite well and give an optimal solution? Will your
answer change if number of coins is odd?
This article is compiled by Aashish Barnwal. Please write comments if you
find anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/dynamic-programming-set-31-optimal-strategy-for-a-game/
170
Chapter 32
Given an input string and a dictionary of words, find out if the input string can
be segmented into a space-separated sequence of dictionary words. See following
examples for more details.
This is a famous Google interview question, also being asked by many other
companies now a days.
Input: ilike
Output: Yes
The string can be segmented as "i like".
Input: ilikesamsung
Output: Yes
The string can be segmented as "i like samsung" or "i like sam sung".
Recursive implementation:
The idea is simple, we consider each prefix and search it in dictionary. If the
prefix is present in dictionary, we recur for rest of the string (or suffix). If the
recursive call for suffix returns true, we return true, otherwise we try next prefix.
If we have tried all prefixes and none of them resulted in a solution, we return
false.
171
We strongly recommend to see substrfunction which is used extensively in
following implementations.
// Base case
if (size == 0) return true;
172
// If we have tried all prefixes and none of them worked
return false;
}
Output:
Yes
Yes
Yes
Yes
Yes
No
Dynamic Programming
Why Dynamic Programming? The above problem exhibits overlapping sub-
problems. For example, see the following partial recursion tree for string “abcde”
in worst case.
173
// A Dynamic Programming based program to test whether a given string can
// be segmented into space separated words in dictionary
#include <iostream>
#include <string.h>
using namespace std;
174
// If we reached the last prefix
if (i == size)
return true;
Output:
Yes
175
Yes
Yes
Yes
Yes
No
Exercise:
The above solutions only finds out whether a given string can be segmented
or not. Extend the above Dynamic Programming solution to print all possible
partitions of input string. See extended recursive solution for reference.
Examples:
Input: ilikeicecreamandmango
Output:
i like ice cream and man go
i like ice cream and mango
i like icecream and man go
i like icecream and mango
Input: ilikesamsungmobile
Output:
i like sam sung mobile
i like samsung mobile
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above
Source
http://www.geeksforgeeks.org/dynamic-programming-set-32-word-break-problem/
Category: Misc Tags: Dynamic Programming
Post navigation
← Amazon Interview | Set 33 Custom Tree Problem →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
176
Chapter 33
177
return true;
Dynamic Programming
The worst case time complexity of recursive solution is O(2n ). The above recur-
sive solution certainly has many overlapping subproblems. For example, if wee
consider A = “XXX”, B = “XXX” and C = “XXXXXX” and draw recursion
tree, there will be many overlapping subproblems.
Therefore, like other typical Dynamic Programming problems, we can solve it by
creating a table and store results of subproblems in bottom up manner. Thanks
to Abhinav Ramana for suggesting this method and implementation.
178
// of lengths of A & B is equal to length of C.
if ((M+N) != strlen(C))
return false;
// A is empty
else if (i==0 && B[j-1]==C[j-1])
IL[i][j] = IL[i][j-1];
// B is empty
else if (j==0 && A[i-1]==C[i-1])
IL[i][j] = IL[i-1][j];
return IL[M][N];
}
179
else
cout << C <<" is not interleaved of " << A <<" and " << B << endl;
}
Output:
Source
http://www.geeksforgeeks.org/check-whether-a-given-string-is-an-interleaving-of-two-other-given-strings-set-
180
Chapter 34
A car factory has two assembly lines, each with n stations. A station is denoted
by Si,j where i is either 1 or 2 and indicates the assembly line the station is
on, and j indicates the number of the station. The time taken per station is
denoted by ai,j . Each station is dedicated to some sort of work like engine fitting,
body fitting, painting and so on. So, a car chassis must pass through each of
the n stations in order before exiting the factory. The parallel stations of the
two assembly lines perform the same task. After it passes through station Si,j ,
it will continue to station Si,j+1 unless it decides to transfer to the other line.
Continuing on the same line incurs no extra cost, but transferring from line i
at station j – 1 to station j on the other line takes time ti,j . Each assembly line
takes an entry time ei and exit time xi which may be different for the two lines.
Give an algorithm for computing the minimum time it will take to build a car
chassis.
The below figure presents the problem in a clear picture:
181
The following information can be extracted from the problem statement to make
it simpler:
182
Base cases:
The entry time ei comes into picture only when the car chassis enters the car
factory.
Time taken to leave first station in line 1 is given by:
T1(1) = Entry time in Line 1 + Time spent in station S1,1
T1(1) = e1 + a1,1
Similarly, time taken to leave first station in line 2 is given by:
T2(1) = e2 + a2,1
Recursive Relations:
If we look at the problem statement, it quickly boils down to the below obser-
vations:
The car chassis at station S1,j can come either from station S1, j-1 or station
S2, j-1 .
Case #1: Its previous station is S1, j-1
The minimum time to leave station S1,j is given by:
T1(j) = Minimum time taken to leave station S1, j-1 + Time spent in station
S1, j
T1(j) = T1(j-1) + a1, j
Case #2: Its previous station is S2, j-1
The minimum time to leave station S1, j is given by:
T1(j) = Minimum time taken to leave station S2, j-1 + Extra cost incurred to
change the assembly line + Time spent in station S1, j
T1(j) = T2(j-1) + t2, j + a1, j
The minimum time T1(j) is given by the minimum of the two obtained in cases
#1 and #2.
T1(j) = min((T1(j-1) + a1, j ), (T2(j-1) + t2, j + a1, j ))
Similarly the minimum time to reach station S2, j is given by:
T2(j) = min((T2(j-1) + a2, j ), (T1(j-1) + t1, j + a2, j ))
The total minimum time taken by the car chassis to come out of the factory is
given by:
Tmin = min(Time taken to leave station Si,n + Time taken to exit the car
factory)
Tmin = min(T1(n) + x1 , T2(n) + x2 )
Why dynamic programming?
The above recursion exhibits overlapping sub-problems. There are two ways to
reach station S1, j :
So, to find the minimum time to leave station S1, j the minimum time to leave
the previous two stations must be calculated(as explained in above recursion).
Similarly, there are two ways to reach station S2, j :
183
1. From station S2, j-1
2. From station S1, j-1
Please note that the minimum times to leave stations S1, j-1 and S2, j-1 have
already been calculated.
So, we need two tables to store the partial results calculated for each station in
an assembly line. The table will be filled in bottom-up fashion.
Note:
In this post, the word “leave” has been used in place of “reach” to avoid the
confusion. Since the car chassis must spend a fixed time in each station, the
word leave suits better.
Implementation:
// Fill tables T1[] and T2[] using the above given recursive relations
for (i = 1; i < NUM_STATION; ++i)
{
T1[i] = min(T1[i-1] + a[0][i], T2[i-1] + t[1][i] + a[0][i]);
T2[i] = min(T2[i-1] + a[1][i], T1[i-1] + t[0][i] + a[1][i]);
}
int main()
{
int a[][NUM_STATION] = {{4, 5, 3, 2},
{2, 10, 1, 4}};
184
int t[][NUM_STATION] = {{0, 7, 4, 5},
{0, 9, 2, 8}};
int e[] = {10, 12}, x[] = {18, 7};
return 0;
}
Output:
35
The bold line shows the path covered by the car chassis for given input values.
Exercise:
Extend the above algorithm to print the path covered by the car chassis in the
factory.
References:
185
Introduction to Algorithms 3rd Edition by Clifford Stein, Thomas H. Cormen,
Charles E. Leiserson, Ronald L. Rivest
This article is compiled by Aashish Barnwal. Please write comments if you
find anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/dynamic-programming-set-34-assembly-line-scheduling/
186
Chapter 35
Given a set of numbers, find the Length of the Longest Arithmetic Progression
(LLAP) in it.
Examples:
For simplicity, we have assumed that the given set is sorted. We can always add
a pre-processing step to first sort the set and then apply the below algorithms.
A simple solution is to one by one consider every pair as first two elements of
AP and check for the remaining elements in sorted set. To consider all pairs as
first two elements, we need to run a O(nˆ2) nested loop. Inside the nested loops,
we need a third loop which linearly looks for the more elements in Arithmetic
Progression (AP). This process takes O(n3 ) time.
We can solve this problem in O(n2 ) time using Dynamic Programming. To
get idea of the DP solution, let us first discuss solution of following simpler
problem.
187
Given a sorted set, find if there exist three elements in Arithmetic
Progression or not
Please note that, the answer is true if there are 3 or more elements in AP, oth-
erwise false.
To find the three elements, we first fix an element as middle element and search
for other two (one smaller and one greater). We start from the second element
and fix every element as middle element. For an element set[j] to be middle
of AP, there must exist elements ‘set[i]’ and ‘set[k]’ such that set[i] + set[k] =
2*set[j] where 0 How to efficiently find i and k for a given j? We can find i and
k in linear time using following simple algorithm.
1) Initialize i as j-1 and k as j+1
2) Do following while i >= 0 and j a) If set[i] + set[k] is equal to 2*set[j], then
we are done.
……..b) If set[i] + set[k] > 2*set[j], then decrement i (do i—).
……..c) Else if set[i] + set[k] // The function returns true if there exist three
elements in AP // Assumption: set[0..n-1] is sorted. // The code strictly imple-
ments the algorithm provided in the reference. bool arithmeticThree(int set[],
int n) { // One by fix every element as middle element for (int j=1; j<n-1; j++)
{ // Initialize i and k for the current j int i = j-1, k = j+1; // Find if there exist
i and k that form AP // with j as middle element while (i >= 0 && k <= n-1)
{ if (set[i] + set[k] == 2*set[j]) return true; (set[i] + set[k] < 2*set[j])? k++ :
i–; } } return false; }
See thisfor a complete running program.
How to extend the above solution for the original problem?
The above function returns a boolean value. The required output of original
problem is Length of the Longest Arithmetic Progression (LLAP) which is an
integer value. If the given set has two or more elements, then the value of LLAP
is at least 2 (Why?).
The idea is to create a 2D table L[n][n]. An entry L[i][j] in this table stores
LLAP with set[i] and set[j] as first two elements of AP and j > i. The last
column of the table is always 2 (Why – see the meaning of L[i][j]). Rest of the
table is filled from bottom right to top left. To fill rest of the table, j (second
element in AP) is first fixed. i and k are searched for a fixed j. If i and k are
found such that i, j, k form an AP, then the value of L[i][j] is set as L[j][k] + 1.
Note that the value of L[j][k] must have been filled before as the loop traverses
from right to left columns.
Following is C++ implementation of the Dynamic Programming algorithm.
// C++ program to find Length of the Longest AP (llap) in a given sorted set.
// The code strictly implements the algorithm provided in the reference.
#include <iostream>
using namespace std;
188
// Returns length of the longest AP subset in a given set
int lenghtOfLongestAP(int set[], int n)
{
if (n <= 2) return n;
else
{
// Found i and k for j, LLAP with i and j as first two
// elements is equal to LLAP with j and k as first two
// elements plus 1. L[j][k] must have been filled
// before as we run the loop from right side
L[i][j] = L[j][k] + 1;
189
}
return 0;
}
Output:
4
3
5
190
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above
Source
http://www.geeksforgeeks.org/length-of-the-longest-arithmatic-progression-in-a-sorted-array/
Category: Misc Tags: Dynamic Programming
Post navigation
← Set 34 (Assembly Line Scheduling) How to check if two given line segments
intersect? →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
191
Chapter 36
Given a rope of length n meters, cut the rope in different parts of integer lengths
in a way that maximizes product of lengths of all parts. You must make at least
one cut. Assume that the length of rope is more than 2 meters.
Examples:
Input: n = 2
Output: 1 (Maximum obtainable product is 1*1)
Input: n = 3
Output: 2 (Maximum obtainable product is 1*2)
Input: n = 4
Output: 4 (Maximum obtainable product is 2*2)
Input: n = 5
Output: 6 (Maximum obtainable product is 2*3)
Input: n = 10
Output: 36 (Maximum obtainable product is 3*3*4)
1) Optimal Substructure:
This problem is similar to Rod Cutting Problem. We can get the maximum prod-
uct by making a cut at different positions and comparing the values obtained
192
after a cut. We can recursively call the same function for a piece obtained after
a cut.
Let maxProd(n) be the maximum product for a rope of length n. maxProd(n)
can be written as following.
maxProd(n) = max(i*(n-i), maxProdRec(n-i)*i) for all i in {1, 2, 3 .. n}
2) Overlapping Subproblems
Following is simple recursive C++ implementation of the problem. The imple-
mentation simply follows the recursive structure mentioned above.
Output:
193
Maximum Product is 36
mP(5)
/ / \ \
/ / \ \
mP(4) mP(3) mP(2) mP(1)
/ | \ / \ |
/ | \ / \ |
mP(3) mP(2) mP(1) mP(2) mP(1) mP(1)
/ \ | |
/ \ | |
mP(2) mP(1) mP(1) mP(1)
In the above partial recursion tree, mP(3) is being solved twice. We can see
that there are many subproblems which are solved again and again. Since same
suproblems are called again, this problem has Overlapping Subprolems property.
So the problem has both properties (see thisand this) of a dynamic programming
problem. Like other typical Dynamic Programming(DP) problems, recomputa-
tions of same subproblems can be avoided by constructing a temporary array
val[] in bottom up manner.
194
return val[n];
}
#include <iostream>
using namespace std;
Output:
195
Maximum Product is 36
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above
Source
http://www.geeksforgeeks.org/dynamic-programming-set-36-cut-a-rope-to-maximize-product/
196
Chapter 37
Set 37 (Boolean
Parenthesization Problem)
Symbols
'T' ---> true
'F' ---> false
Operators
& ---> boolean AND
| ---> boolean OR
^ ---> boolean XOR
Count the number of ways we can parenthesize the expression so that the value
of expression evaluates to true.
Let the input be in form of two arrays one contains the symbols (T and F) in
order and other contains operators (&, | and ˆ}
Examples:
197
Input: symbol[] = {T, F, T}
operator[] = {^, &}
Output: 2
The given expression is "T ^ F & T", it evaluates true
in two ways "((T ^ F) & T)" and "(T ^ (F & T))"
Solution:
Let T(i, j) represents the number of ways to parenthesize the symbols between
i and j (both inclusive) such that the subexpression between i and j evaluates
to true.
Let F(i, j) represents the number of ways to parenthesize the symbols between
i and j (both inclusive) such that the subexpression between i and j evaluates
to false.
Base Cases:
198
F(i, i) = 0 if symbol[i] = 'T'
#include<iostream>
#include<cstring>
using namespace std;
199
int tkj = T[k+1][j] + F[k+1][j];
Output:
200
Time Complexity: O(n3 )
Auxiliary Space: O(n2 )
References:
http://people.cs.clemson.edu/~bcdean/dp_practice/dp_9.swf
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above
Source
http://www.geeksforgeeks.org/dynamic-programming-set-37-boolean-parenthesization-problem/
Category: Misc
Post navigation
← Pilani Soft Labs (redBus) Interview Print substring of a given string without
using any string function and loop in C →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
201
Chapter 38
202
we want to represent a subset of this set than it can be encoded by a sequence
of N bits (we usually call this sequence a “mask”). In our chosen subset the i-th
element belongs to it if and only if the i-th bit of the mask I set i.e., it equals
to 1. For example, the mask 10000101 means that the subset of the set [1…
8] consists of elements 1, 3 and 8. We know that for a set of N elements there
are total 2N subsets thus 2N masks are possible, one representing each subset.
Each mask is in fact an integer number written in binary notation.
Our main methodology is to assign a value to each mask (and, therefore, to
each subset) and thus calculate the values for new masks using values of the
already computed masks. Usually our main target is to calculate value/solution
for the complete set i.e., for mask 11111111. Normally, to find the value for a
subset X we remove an element in every possible way and use values for obtained
subsets X’1 , X’2 … ,X’k to compute the value/solution for X. This means that
the values for X’i must have been computed already, so we need to establish an
ordering in which masks will be considered. It’s easy to see that the natural
ordering will do: go over masks in increasing order of corresponding numbers.
Also, We sometimes, start with the empty subset X and we add elements in
every possible way and use the values of obtained subsets X’1 , X’2 … ,X’k to
compute the value/solution for X.
We mostly use the following notations/operations on masks:
bit(i,mask) – the i-th bit of mask
count(mask) – the number of non-zero bits in mask
first(mask) – the number of the lowest non-zero bit in mask
set(i, mask) – set the ith bit in mask
check(i, mask) – check the ith bit in mask
How is this problem solved using Bitmasking + DP?
The idea is to use the fact that there are upto 10 persons. So we can use a
integer variable as a bitmask to store which person is wearing cap and which is
not.
Let i be the current cap number (caps from 1 to i-1 are already
processed). Let integer variable mask indicates the the persons w
earing and not wearing caps. If i'th bit is set in mask, then
i'th person is wearing a cap, else not.
203
If we draw the complete recursion tree, we can observer that many subproblems are solved again a
Since we want to access all persons that can wear a given cap, we use an array of vectors, capLis
Below is C++ implementation of above idea.
// This is used for base case, it has all the N bits set
// so, it tells whether all N persons are wearing a cap.
int allmask;
204
// So, assign one by one ith cap to all the possible persons
// and recur for remaining caps.
for (int j = 0; j < size; j++)
{
// if person capList[i][j] is already wearing a cap so continue as
// we cannot assign him this cap
if (mask & (1 << capList[i][j])) continue;
// Else assign him this cap and recur for remaining caps with
// new updated mask vector
else ways += countWaysUtil(mask | (1 << capList[i][j]), i+1);
ways %= MOD;
}
205
// Initialize all entries in dp as -1
memset(dp, -1, sizeof dp);
// Driver Program
int main()
{
int n; // number of persons in every test case
cin >> n;
countWays(n);
return 0;
}
Input:
3
5 100 1
2
5 100
Output:
Source
http://www.geeksforgeeks.org/bitmasking-and-dynamic-programming-set-1-count-ways-to-assign-unique-cap
206
Chapter 39
Given a matrix where every cell represents points. How to collect maximum
points using two traversals under following conditions?
Let the dimensions of given grid be R x C.
1) The first traversal starts from top left corner, i.e., (0, 0) and should reach left
bottom corner, i.e., (R-1, 0). The second traversal starts from top right corner,
i.e., (0, C-1) and should reach bottom right corner, i.e., (R-1, C-1)/
2) From a point (i, j), we can move to (i+1, j+1) or (i+1, j-1) or (i+1, j)
3) A traversal gets all points of a particular cell through which it passes. If one
traversal has already collected points of a cell, then the other traversal gets no
points if goes through that cell again.
Input :
int arr[R][C] = {{3, 6, 8, 2},
{5, 2, 4, 3},
{1, 1, 20, 10},
{1, 1, 20, 10},
{1, 1, 20, 10},
};
Output: 73
Explanation :
207
Second traversal collects total points of value 2 + 4 + 10 + 20 + 10 = 46.
Total Points collected = 27 + 46 = 73.
Source: http://qa.geeksforgeeks.org/1485/running-through-the-grid-to-get-maximum-nutritional-value
We strongly recommend you to minimize your browser and try this
yourself first.
The idea is to do both traversals concurrently. We start first from (0, 0) and
second traversal from (0, C-1) simultaneously. The important thing to note
is, at any particular step both traversals will be in same row as in all possible
three moves, row number is increased. Let (x1, y1) and (x2, y2) denote current
positions of first and second traversals respectively. Thus at any time x1 will
be equal to x2 as both of them move forward but variation is possible along y.
Since variation in y could occur in 3 ways no change (y), go left (y – 1), go right
(y + 1). So in total 9 combinations among y1, y2 are possible. The 9 cases as
mentioned below after base cases.
// If both traversals are at same cell, then we count the value of cell
// only once.
If y1 and y2 are same
result = arr[x][y1]
Else
result = arr[x][y1] + arr[x][y2]
208
maxPoints(arr, x+1, y1, y2-1)
}
The above recursive solution has many subproblems that are solved again and
again. Therefore, we can use Dynamic Programming to solve the above prob-
lem more efficiently. Below is memoization (Memoization is alternative to table
based iterative solution in Dynamic Programming) based implementation. In
below implementation, we use a memoization table ‘mem’ to keep track of al-
ready solved problems.
209
int ans = INT_MIN;
/* Recur for all possible cases, then store and return the
one with max value */
ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1, y2-1));
ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1, y2+1));
ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1, y2));
210
return 0;
}
Output:
Maximum collection is 73
Thanks to Gaurav Ahirwar for suggesting above problem and solution here.
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/collect-maximum-points-in-a-grid-using-two-traversals/
Category: Arrays Tags: Dynamic Programming, Matrix
Post navigation
← Amazon Interview Experience | Set 213 (Off-Campus for SDE1) Amazon
Interview Experience | 214 (On-Campus) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
211
Chapter 40
Input: n = 5
Output: Sum of digits in numbers from 1 to 5 = 15
Input: n = 12
Output: Sum of digits in numbers from 1 to 12 = 51
Input: n = 328
Output: Sum of digits in numbers from 1 to 328 = 3241
Naive Solution:
A naive solution is to go through every number x from 1 to n, and compute sum
in x by traversing all digits of x. Below is C++ implementation of this idea.
int sumOfDigits(int );
212
// Returns sum of all digits in numbers from 1 to n
int sumOfDigitsFrom1ToN(int n)
{
int result = 0; // initialize result
return result;
}
// Driver Program
int main()
{
int n = 328;
cout << "Sum of digits in numbers from 1 to " << n << " is "
<< sumOfDigitsFrom1ToN(n);
return 0;
}
Output
Efficient Solution:
Above is a naive solution. We can do it more efficiently by finding a pattern.
Let us take few examples.
213
sum(9) = 1 + 2 + 3 + 4 ........... + 9
= 9*10/2
= 45
214
b) Sum of digits in msd * 10d to n. For 328, sum of digits in
300 to 328.
For 328, this sum is computed as 3*29 + recursive call "sum(28)"
In general, this sum can be computed as msd * (n % (msd*10d) + 1)
+ sum(n % (10d))
// computing 10^d
int p = ceil(pow(10, d));
215
// First two terms compute sum of digits from 1 to 299
// (sum of digits in range 1-99 stored in a[d]) +
// (sum of digits in range 100-199, can be calculated as 1*100 + a[d]
// (sum of digits in range 200-299, can be calculated as 2*100 + a[d]
// The above sum can be written as 3*a[d] + (1+2)*100
// Driver Program
int main()
{
int n = 328;
cout << "Sum of digits in numbers from 1 to " << n << " is "
<< sumOfDigitsFrom1ToN(n);
return 0;
}
Output
The efficient algorithm has one more advantage that we need to compute the
array ‘a[]’ only once even when we are given multiple inputs.
This article is computed by Shubham Gupta. Please write comments if you
find anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/count-sum-of-digits-in-numbers-from-1-to-n/
Category: Misc Tags: Dynamic Programming, MathematicalAlgo
216
Chapter 41
Let 1 represent ‘A’, 2 represents ‘B’, etc. Given a digit sequence, count the
number of possible decodings of the given digit sequence.
Examples:
217
2) If the last two digits form a valid character (or smaller than 27), recur for
remaining (n-2) digits and add the result to total count.
Following is C++ implementation of the above approach.
// If the last two digits form a number smaller than or equal to 26,
// then consider last two digits and recur
if (digits[n-2] < '2' || (digits[n-2] == '2' && digits[n-1] < '7') )
count += countDecoding(digits, n-2);
return count;
}
218
Output:
Count is 3
The time complexity of above the code is exponential. If we take a closer look
at the above program, we can observe that the recursive solution is similar to
Fibonacci Numbers. Therefore, we can optimize the above solution to work in
O(n) time using Dynamic Programming. Following is C++ implementation for
the same.
219
int n = strlen(digits);
cout << "Count is " << countDecodingDP(digits, n);
return 0;
}
Output:
Count is 3
Time Complexity of the above solution is O(n) and it requires O(n) auxiliary
space. We can reduce auxiliary space to O(1) by using space optimized version
discussed in the Fibonacci Number Post.
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above
Source
http://www.geeksforgeeks.org/count-possible-decodings-given-digit-sequence/
Category: Strings Tags: Dynamic Programming, Fibonacci numbers, Mathe-
maticalAlgo
220
Chapter 42
The problem is to count all the possible paths from top left to bottom right of a
mXn matrix with the constraints that from each cell you can either move
only to right or down
We have discussed a solution to print all possible paths, counting all paths is
easier. Let NumberOfPaths(m, n) be the count of paths to reach row number m
and column number n in the matrix, NumberOfPaths(m, n) can be recursively
written as following.
#include <iostream>
using namespace std;
// Returns count of possible paths to reach cell at row number m and column
// number n from the topmost leftmost cell (cell at 1, 1)
int numberOfPaths(int m, int n)
{
// If either given row number is first or given column number is first
if (m == 1 || n == 1)
return 1;
221
}
int main()
{
cout << numberOfPaths(3, 3);
return 0;
}
Output:
The time complexity of above recursive solution is exponential. There are many
overlapping subproblems. We can draw a recursion tree for numberOfPaths(3,
3) and see many overlapping subproblems. The recursion tree would be similar
to Recursion tree for Longest Common Subsequence problem.
So this problem has both properties (see this and this) of a dynamic program-
ming problem. Like other typical Dynamic Programming(DP) problems, re-
computations of same subproblems can be avoided by constructing a temporary
array count[][] in bottom up manner using the above recursive formula.
#include <iostream>
using namespace std;
// Returns count of possible paths to reach cell at row number m and column
// number n from the topmost leftmost cell (cell at 1, 1)
int numberOfPaths(int m, int n)
{
// Create a 2D table to store results of subproblems
int count[m][n];
222
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
}
return count[m-1][n-1];
}
Output:
Note the count can also be calculated using the formula (m-1
+ n-1)!/(m-1)!(n-1)!. See this for more details.
This article is contributed by Hariprasad NG. Please write comments if you
find anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/count-possible-paths-top-left-bottom-right-nxm-matrix/
Category: Arrays Tags: Dynamic Programming
223
Chapter 43
Given a directed graph and two vertices ‘u’ and ‘v’ in it, count all possible walks
from ‘u’ to ‘v’ with exactly k edges on the walk.
The graph is given as adjacency matrix representation where value of graph[i][j]
as 1 indicates that there is an edge from vertex i to vertex j and a value 0
indicates no edge from i to j.
For example consider the following graph. Let source ‘u’ be vertex 0, destination
‘v’ be 3 and k be 2. The output should be 2 as there are two walk from 0 to 3
with exactly 2 edges. The walks are {0, 2, 3} and {0, 1, 3}
224
We strongly recommend to minimize the browser and try this yourself
first.
A simple solution is to start from u, go to all adjacent vertices and recur for
adjacent vertices with k as k-1, source as adjacent vertex and destination as v.
Following is C++ implementation of this simple solution.
// Initialize result
int count = 0;
225
// Go to all adjacents of u and recur
for (int i = 0; i < V; i++)
if (graph[u][i]) // Check if is adjacent of u
count += countwalks(graph, i, v, k-1);
return count;
}
Output:
The worst case time complexity of the above function is O(Vk ) where V is
the number of vertices in the given graph. We can simply analyze the time
complexity by drawing recursion tree. The worst occurs for a complete graph.
In worst case, every internal node of recursion tree would have exactly n children.
We can optimize the above solution using Dynamic Programming. The idea
is to build a 3D table where first dimension is source, second dimension is
destination, third dimension is number of edges from source to destination, and
the value is count of walks. Like other Dynamic Programming problems, we fill
the 3D table in bottom up manner.
226
#define V 4
227
{0, 0, 0, 0}
};
int u = 0, v = 3, k = 2;
cout << countwalks(graph, u, v, k);
return 0;
}
Output:
Time complexity of the above DP based solution is O(V3 K) which is much better
than the naive solution.
We can also use Divide and Conquer to solve the above problem in O(V3 Logk)
time. The count of walks of length k from u to v is the [u][v]’th entry in
(graph[V][V])k . We can calculate power of by doing O(Logk) multiplication by
using the divide and conquer technique to calculate power. A multiplication
between two matrices of size V x V takes O(V3 ) time. Therefore overall time
complexity of this method is O(V3 Logk).
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above.
Source
http://www.geeksforgeeks.org/count-possible-paths-source-destination-exactly-k-edges/
Category: Graph Tags: Dynamic Programming
Post navigation
← Amazon Interview | Set 100 (On-Campus) A Problem in Many Binary Search
Implementations →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
228
Chapter 44
Given a number n, find count of all binary sequences of length 2n such that sum
of first n bits is same as sum of last n bits.
Examples:
Input: n = 1
Output: 2
There are 2 sequences of length 2*n, the
sequences are 00 and 11
Input: n = 2
Output: 2
There are 6 sequences of length 2*n, the
sequences are 0101, 0110, 1010, 1001, 0000
and 1111
229
have the same sum.
2) First bit is 1 and last bit is 0, sum of remaining n-1 bits on left side should
be 1 less than the sum n-1 bits on right side.
2) First bit is 0 and last bit is 1, sum of remaining n-1 bits on left side should
be 1 more than the sum n-1 bits on right side.
Based on above facts, we get below recurrence formula.
diff is the expected difference between sum of first half digits and last half digits.
Initially diff is 0.
230
// than n with 2n bits
if (abs(diff) > n)
return 0;
return res;
}
// Driver program
int main()
{
int n = 2;
cout << "Count of sequences is "
<< countSeq(2, 0);
return 0;
}
Output
Count of sequences is 6
231
// A memoization based C++ program to count even
// length binary sequences such that the sum of
// first and second half bits is same
#include<bits/stdc++.h>
using namespace std;
#define MAX 1000
232
// A Wrapper over countSeqUtil(). It mainly initializes lookup
// table, then calls countSeqUtil()
int countSeq(int n)
{
// Initialize all entries of lookup table as not filled
memset(lookup, -1, sizeof(lookup));
// call countSeqUtil()
return countSeqUtil(n, 0);
}
// Driver program
int main()
{
int n = 2;
cout << "Count of sequences is "
<< countSeq(2);
return 0;
}
Output
Count of sequences is 6
Worst case time complexity of this solution is O(n2 ) as diff can be maximum n.
Below is O(n) solution for the same.
No. of 2*n bit strings such that first n bits have 0 ones &
last n bits have 0 ones = nC0 * nC0
233
No. of 2*n bit strings such that first n bits have 1 ones &
last n bits have 1 ones = nC1 * nC1
....
and so on.
res += nCr*nCr;
}
return res;
}
// Driver program
int main()
{
int n = 3;
cout << "Count of sequences is "
<< countSeq(n);
return 0;
}
234
Output
Count of sequences is 6
Thanks to d_geeks, Saurabh Jain and Mysterious Mind for suggesting above
O(n) solution.
This article is contributed by Pawan. Please write comments if you find anything
incorrect, or you want to share more information about the topic discussed above
Source
http://www.geeksforgeeks.org/count-even-length-binary-sequences-with-same-sum-of-first-and-second-half-bi
Category: Misc Tags: Dynamic Programming
Post navigation
← 10 mistakes people tend to do in an Interview Adobe Interview Experience |
Set 30 (Off-Campus For Member Technical Staff) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
235
Chapter 45
Given a positive integer N, count all possible distinct binary strings of length N
such that there are no consecutive 1’s.
Examples:
Input: N = 2
Output: 3
// The 3 strings are 00, 01, 10
Input: N = 3
Output: 5
// The 5 strings are 000, 001, 010, 100, 101
This problem can be solved using Dynamic Programming. Let a[i] be the number
of binary strings of length i which do not contain any two consecutive 1’s and
which end in 0. Similarly, let b[i] be the number of such strings which end in 1.
We can append either 0 or 1 to a string ending in 0, but we can only append 0
to a string ending in 1. This yields the recurrence relation:
236
The base cases of above recurrence are a[1] = b[1] = 1. The total number of
strings of length i is just a[i] + b[i].
Following is C++ implementation of above solution. In the following implemen-
tation, indexes start from 0. So a[i] represents the number of binary strings for
input length i+1. Similarly, b[i] represents binary strings for input length i+1.
int countStrings(int n)
{
int a[n], b[n];
a[0] = b[0] = 1;
for (int i = 1; i < n; i++)
{
a[i] = a[i-1] + b[i-1];
b[i] = a[i-1];
}
return a[n-1] + b[n-1];
}
Output:
Source:
courses.csail.mit.edu/6.006/oldquizzes/solutions/q2-f2009-sol.pdf
This article is contributed by Rahul Jain. Please write comments if you find
anything incorrect, or you want to share more information about the topic
discussed above
237
Source
http://www.geeksforgeeks.org/count-number-binary-strings-without-consecutive-1s/
Category: Arrays Tags: Dynamic Programming
238
Chapter 46
Given a distance ‘dist, count total number of ways to cover the distance with 1,
2 and 3 steps.
Examples:
Input: n = 3
Output: 4
Below are the four ways
1 step + 1 step + 1 step
1 step + 2 step
2 step + 1 step
3 step
Input: n = 4
Output: 7
239
// Returns count of ways to cover 'dist'
int printCountRec(int dist)
{
// Base cases
if (dist<0) return 0;
if (dist==0) return 1;
// driver program
int main()
{
int dist = 4;
cout << printCountRec(dist);
return 0;
}
Output:
240
#include<iostream>
using namespace std;
return count[dist];
}
// driver program
int main()
{
int dist = 4;
cout << printCountDP(dist);
return 0;
}
Output: 4
This article is contributed by Vignesh Venkatesan. Please write comments if
you find anything incorrect, or you want to share more information about the
topic discussed above
Source
http://www.geeksforgeeks.org/count-number-of-ways-to-cover-a-distance/
Category: Misc Tags: Dynamic Programming
241
Chapter 47
Input: n = 20
Output: 4
There are following 4 ways to reach 20
(10, 10)
(5, 5, 10)
(5, 5, 5, 5)
(3, 3, 3, 3, 3, 5)
Input: n = 13
Output: 2
There are following 2 ways to reach 13
(3, 5, 5)
(3, 10)
242
This problem is a variation of coin change problem and can be solved in O(n)
time and O(n) auxiliary space.
The idea is to create a table of size n+1 to store counts of all scores from 0 to
n. For every possible move (3, 5 and 10), increment values in table.
return table[n];
}
// Driver program
int main(void)
{
int n = 20;
printf("Count for %d is %d\n", n, count(n));
n = 13;
printf("Count for %d is %d", n, count(n));
243
return 0;
}
Output:
Count for 20 is 4
Count for 13 is 2
Exercise: How to count score when (10, 5, 5), (5, 5, 10) and (5, 10, 5) are
considered as different sequences of moves. Similarly, (5, 3, 3), (3, 5, 3) and (3,
3, 5) are considered different.
This article is contributed by Rajeev Arora. Please write comments if you
find anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/count-number-ways-reach-given-score-game/
Category: Misc Tags: Dynamic Programming
244
Chapter 48
Given two integers ‘n’ and ‘sum’, find count of all n digit numbers with sum of
digits as ‘sum’. Leading 0’s are not counted as digits.
1
Example:
Input: n = 2, sum = 2
Output: 2
Explanation: Numbers are 11 and 20
Input: n = 2, sum = 5
Output: 5
Explanation: Numbers are 14, 23, 32, 41 and 50
Input: n = 3, sum = 6
Output: 21
245
countRec(n, sum) = �finalCount(n-1, sum-x)
where 1 == 0
One important observation is, leading 0's must be
handled explicitly as they are not counted as digits.
So our final count can be written as below.
// Initialize answer
unsigned long long int ans = 0;
return ans;
}
246
{
// Initialize final answer
unsigned long long int ans = 0;
return ans;
}
// Driver program
int main()
{
int n = 2, sum = 5;
cout << finalCount(n, sum);
return 0;
}
Output:
247
unsigned long long int lookup[101][50001];
// Initialize answer
unsigned long long int ans = 0;
248
// Driver program
int main()
{
int n = 3, sum = 5;
cout << finalCount(n, sum);
return 0;
}
Output:
Source
http://www.geeksforgeeks.org/count-of-n-digit-numbers-whose-sum-of-digits-equals-to-given-sum/
Category: Misc Tags: Dynamic Programming
Post navigation
← Minimum Initial Points to Reach Destination Microsoft IDC Interview Ex-
perience | Set 68 (For SDE) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
249
Chapter 49
Given an input number of sections and each section has 2 plots on either sides
of the road. Find all possible ways to construct buildings in the plots such that
there is a space between any 2 buildings.
Example:
N = 1
Output = 4
Place a building on one side.
Place a building on other side
Do not place any building.
Place a building on both sides.
N = 3
Output = 25
3 sections, which means possible ways for one side are
BSS, BSB, SSS, SBS, SSB where B represents a building
and S represents an empty space
Total possible ways are 25, because a way to place on
one side can correspond to any of 5 ways on other side.
N = 4
Output = 64
250
We strongly recommend to minimize your browser and try this your-
self first
We can simplify the problem to first calculate for one side only. If we know the
result for one side, we can always do square of the result and get result for two
sides.
A new building can be placed on a section if section just before it has space. A
space can be placed anywhere (it doesn’t matter whether the previous section
has a building or not).
251
// prev_countB and prev_countS are previous values of
// countB and countS respectively.
// Driver program
int main()
{
int N = 3;
cout << "Count of ways for " << N
<< " sections is " << countWays(N);
return 0;
}
Output:
25
252
Optimized Solution:
Note that the above solution can be further optimized. If we take closer look at
the results, for different values, we can notice that the results for two sides are
squares of Fibonacci Numbers.
N = 1, result = 4 [result for one side = 2]
N = 2, result = 9 [result for one side = 3]
N = 3, result = 25 [result for one side = 5]
N = 4, result = 64 [result for one side = 8]
N = 5, result = 169 [result for one side = 13]
…………………….
…………………….
In general, we can say
result(N) = fib(N+2)2
Source
http://www.geeksforgeeks.org/count-possible-ways-to-construct-buildings/
253
Chapter 50
Given a number n, we need to count total number of n digit numbers such that
the sum of even digits is 1 more than the sum of odd digits. Here even and
odd means positions of digits are like array indexes, for exampl, the leftmost (or
leading) digit is considered as even digit, next to leftmost is considered as odd
and so on.
Example
Input: n = 2
Output: Required Count of 2 digit numbers is 9
Explanation : 10, 21, 32, 43, 54, 65, 76, 87, 98.
Input: n = 3
Output: Required Count of 3 digit numbers is 54
Explanation: 100, 111, 122, ......, 980
254
This problem is mainly an extension of Count of n digit numbers whose sum of
digits equals to given sum. Here the solution of subproblems depend on four
variables: digits, esum (current even sum), osum (current odd sum), isEven(A
flag to indicate whether current digit is even or odd).
Below is Memoization based solution for the same.
// Initialize result
unsigned long long int ans = 0;
255
// This is mainly a wrapper over countRec. It
// explicitly handles leading digit and calls
// countRec() for remaining digits.
unsigned long long int finalCount(int n)
{
// Initialize number digits considered so far
int digits = 0;
return ans;
}
// Driver program
int main()
{
int n = 3;
cout << "Coutn of "<<n << " digit numbers is " << finalCount(n);
return 0;
}
Output:
256
Source
http://www.geeksforgeeks.org/count-total-number-of-n-digit-numbers-such-that-the-difference-between-the-s
Category: Misc Tags: Dynamic Programming
Post navigation
← Intuit Interview | Set 9 (On-Campus) USA’s Love for Indian CEOs →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
257
Chapter 51
There are n stairs, a person standing at the bottom wants to reach the top. The
person can climb either 1 stair or 2 stairs at a time. Count the number of ways,
the person can reach the top.
Consider the example shown in diagram. The value of n is 3. There are 3 ways
to reach the top. The diagram is taken from Easier Fibonacci puzzles
258
More Examples:
Input: n = 1
Output: 1
There is only one way to climb 1 stair
Input: n = 2
Output: 2
There are two ways: (1, 1) and (2)
Input: n = 4
Output: 5
(1, 1, 1, 1), (1, 1, 2), (2, 1, 1), (1, 2, 1), (2, 2)
We can easily find recursive nature in above problem. The person can reach
n’th stair from either (n-1)’th stair or from (n-2)’th stair. Let the total number
of ways to reach n’t stair be ‘ways(n)’. The value of ‘ways(n)’ can be written as
following.
The above expression is actually the expression for Fibonacci numbers, but there
is one thing to notice, the value of ways(n) is equal to fibonacci(n+1).
ways(1) = fib(2) = 1
ways(2) = fib(3) = 2
ways(3) = fib(4) = 3
So we can use function for fibonacci numbers to find the value of ways(n). Fol-
lowing is C++ implementation of the above idea.
259
int fib(int n)
{
if (n <= 1)
return n;
return fib(n-1) + fib(n-2);
}
Output:
Number of ways = 5
260
// A C program to count number of ways to reach n't stair when
// a person can climb either 1 or 2 stairs at a time
#include<stdio.h>
Output:
Number of ways = 5
261
// A recursive function used by countWays
int countWaysUtil(int n, int m)
{
int res[n];
res[0] = 1; res[1] = 1;
for (int i=2; i<n; i++)
{
res[i] = 0;
for (int j=1; j<=m && j<=i; j++)
res[i] += res[i-j];
}
return res[n-1];
}
Output:
Number of ways = 5
Source
http://www.geeksforgeeks.org/count-ways-reach-nth-stair/
262
Chapter 52
Given a matrix of characters. Find length of the longest path from a given
character, such that all characters in the path are consecutive to each other, i.e.,
every character in path is next to previous in alphabetical order. It is allowed
to move in all 8 directions from a cell.
Example
263
Input: mat[][] = { {a, c, d},
{h, b, e},
{i, g, f}}
Starting Point = 'e'
Output: 5
If starting point is 'e', then longest path with consecutive
characters is "e f g h i".
Output: 1
'c' is not present in all adjacent cells of 'b'
264
bool isvalid(int i, int j)
{
if (i < 0 || j < 0 || i >= R || j >= C)
return false;
return true;
}
265
{
memset(dp, -1, sizeof dp);
int ans = 0;
// Driver program
int main() {
Output:
4
0
3
4
266
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above
Source
http://www.geeksforgeeks.org/find-length-of-the-longest-consecutive-path-in-a-character-matrix/
Category: Arrays Tags: Dynamic Programming, Matrix
Post navigation
← Fiberlink (maas360) Interview Experience | Set 4 (Off-Campus) Goldman
Sachs Interview Experience | Set 10 (On-Campus) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
267
Chapter 53
Given a value V, if we want to make change for V cents, and we have infinite
supply of each of C = { C1, C2, .. , Cm} valued coins, what is the minimum
number of coins to make the change?
Examples:
268
If V == 0, then 0 coins required.
If V > 0
minCoin(coins[0..m-1], V) = min {1 + minCoins(V-coin[i])}
where i varies from 0 to m-1
and coin[i]
Below is recursive solution based on above recursive formula.
// Initialize result
int res = INT_MAX;
269
return 0;
}
Output:
270
{
// Go through all coins smaller than i
for (int j=0; j<m; j++)
if (coins[j] <= i)
{
int sub_res = table[i-coins[j]];
if (sub_res != INT_MAX && sub_res + 1 < table[i])
table[i] = sub_res + 1;
}
}
return table[V];
}
Output:
Source
http://www.geeksforgeeks.org/find-minimum-number-of-coins-that-make-a-change/
Category: Arrays Tags: Dynamic Programming
Post navigation
271
← Drishti-Soft Solutions Interview | Set 2 (On-Campus Written) Adobe Inter-
view Experience | Set 23 (1 Year Experienced) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
272
Chapter 54
Given an array of numbers and a constant k, minimize size of array with follow-
ing rules for removing elements.
Example:
273
Source: https://code.google.com/codejam/contest/4214486/dashboard#s=p2
We strongly recommend you to minimize your browser and try this
yourself first.
For every element arr[i] there are two possibilities
1) Either the element is not removed.
2) OR element is removed (if it follows rules of removal). When an element is
removed, there are again two possibilities.
…..a) It may be removed directly, i.e., initial arr[i+1] is arr[i]+k and arr[i+2] is
arr[i] + 2*k.
…..b) There exist x and y such that arr[x] – arr[i] = k, arr[y] – arr[x] = k, and
subarrays “arr[i+1…x-1]” & “arr[x+1…y-1]” can be completely removed.
Below is recursive algorithm based on above idea.
4) Return result
274
Below is C++ implementation of above idea. The implementation is memo-
ization based, i.e., it is recursive and uses a lookup table dp[][] to check if a
subproblem is already solved or not.
275
}
Output:
This article is contributed by Ekta Goel. Please write comments if you find
anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/find-minimum-possible-size-of-array-with-given-rules-for-removal/
Category: Arrays Tags: Dynamic Programming
Post navigation
← Microsoft Interview experience | Set 73 (On-Campus for IT SDE Intern)
Microsoft Interview Experience | Set 74 (For Software Engineer in IT Team) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
276
Chapter 55
277
If rhs = 0
countSol(coeff, 0, rhs, n-1) = 1
Else
countSol(coeff, 0, rhs, n-1) = ∑countSol(coeff, i, rhs-coeff[i], m-1)
where coeff[i]
Below is recursive C++ implementation of above solution.
return result;
}
// Driver program
int main()
{
int coeff[] = {2, 2, 5};
int rhs = 4;
int n = sizeof(coeff)/sizeof(coeff[0]);
cout << countSol(coeff, 0, n-1, rhs);
return 0;
}
Output:
278
The time complexity of above solution is exponential. We can solve this problem
in Pseudo Polynomial Time (time complexity is dependent on numeric value of
input) using Dynamic Programming. The idea is similar to Dynamic Program-
ming solution Subset Sum problem. Below is Dynamic Programming based
C++ implementation.
return dp[rhs];
}
// Driver program
int main()
{
int coeff[] = {2, 2, 5};
int rhs = 4;
int n = sizeof(coeff)/sizeof(coeff[0]);
cout << countSol(coeff, n, rhs);
return 0;
}
Output:
279
3
Source
http://www.geeksforgeeks.org/find-number-of-solutions-of-a-linear-equation-of-n-variables/
Category: Misc Tags: Dynamic Programming, MathematicalAlgo
Post navigation
← Factset Interview Experience | Set 6 (On-Campus) Dolat Capital Interview
experience | Set 1 (On-Campus) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
280
Chapter 56
Given a n*n matrix where numbers all numbers are distinct and are distributed
from range 1 to n2 , find the maximum length path (starting from any cell) such
that all cells along the path are increasing order with a difference of 1.
We can move in 4 directions from a given cell (i, j), i.e., we can move to (i+1, j)
or (i, j+1) or (i-1, j) or (i, j-1) with the condition that the adjacen
Example:
281
#include<bits/stdc++.h>
#define n 3
using namespace std;
if (mat[i][j] +1 == mat[i][j-1])
return dp[i][j] = 1 + findLongestFromACell(i,j-1,mat,dp);
if (mat[i][j] +1 == mat[i-1][j])
return dp[i][j] = 1 + findLongestFromACell(i-1,j,mat,dp);
if (mat[i][j] +1 == mat[i+1][j])
return dp[i][j] = 1 + findLongestFromACell(i+1,j,mat,dp);
282
{
for (int j=0; j<n; j++)
{
if (dp[i][j] == -1)
findLongestFromACell(i, j, mat, dp);
return result;
}
// Driver program
int main()
{
int mat[n][n] = {{1, 2, 9},
{5, 3, 8},
{4, 6, 7}};
cout << "Length of the longest path is "
<< finLongestOverAll(mat);
return 0;
}
Output:
Time complexity of the above solution is O(n2 ). It may seem more at first look.
If we take a closer look, we can notice that all values of dp[i][j] are computed
only once.
This article is contributed by Ekta Goel. Please write comments if you find
anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/find-the-longest-path-in-a-matrix-with-given-constraints/
Category: Arrays Tags: Dynamic Programming, Matrix
283
Post navigation
← Sort a stack using recursion Paytm Interview Experience | Set 5 (Recruitment
Drive) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
284
Chapter 57
There are N stations on route of a train. The train goes from station 0 to N-1.
The ticket cost for all pair of stations (i, j) is given where j is greater than i.
Find the minimum cost to reach the destination.
Consider the following example:
Input:
cost[N][N] = { {0, 15, 80, 90},
{INF, 0, 40, 50},
{INF, INF, 0, 70},
{INF, INF, INF, 0}
};
There are 4 stations and cost[i][j] indicates cost to reach j
from i. The entries where j
We strongly recommend to minimize your browser and try this yourself first.
The minimum cost to reach N-1 from 0 can be recursively written as following:
285
The following is C++ implementation of above recursive formula.
// infinite value
#define INF INT_MAX
// Number of stations
#define N 4
286
// Driver program to test above function
int main()
{
int cost[N][N] = { {0, 15, 80, 90},
{INF, 0, 40, 50},
{INF, INF, 0, 70},
{INF, INF, INF, 0}
};
cout << "The Minimum cost to reach station "
<< N << " is " << minCost(cost);
return 0;
}
Output:
287
3) The min cost for station 2 is minimum of following two.
a) dist[0] + cost[0][2]
b) dist[1] + cost[1][2]
3) The min cost for station 3 is minimum of following three.
a) dist[0] + cost[0][3]
b) dist[1] + cost[1][3]
c) dist[2] + cost[2][3]
Similarly, dist[4], dist[5], … dist[N-1] are calculated.
Below is C++ implementation of above idea.
return dist[N-1];
}
288
int cost[N][N] = { {0, 15, 80, 90},
{INF, 0, 40, 50},
{INF, INF, 0, 70},
{INF, INF, INF, 0}
};
cout << "The Minimum cost to reach station "
<< N << " is " << minCost(cost);
return 0;
}
Output:
Source
http://www.geeksforgeeks.org/find-the-minimum-cost-to-reach-a-destination-where-every-station-is-connecte
Category: Graph Tags: Dynamic Programming
Post navigation
← Fiberlink (maas360) Interview | Set 2 (Written Test Question) VMWare
Interview Experience | Set 2 (On-Campus) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
289
Chapter 58
This is a famous interview question asked in Google, Paytm and many other
company interviews.
Below is the problem statement.
If you can only press the keyboard for N times (with the above four
keys), write a program to produce maximum numbers of A's. That is to
say, the input parameter is N (No. of keys that you can press), the
output is M (No. of As that you can produce).
Examples:
Input: N = 3
Output: 3
290
We can at most get 3 A's on screen by pressing
following key sequence.
A, A, A
Input: N = 7
Output: 9
We can at most get 9 A's on screen by pressing
following key sequence.
A, A, A, Ctrl A, Ctrl C, Ctrl V, Ctrl V
Input: N = 11
Output: 27
We can at most get 27 A's on screen by pressing
following key sequence.
A, A, A, Ctrl A, Ctrl C, Ctrl V, Ctrl V, Ctrl A,
Ctrl C, Ctrl V, Ctrl V
291
// Initialize result
int max = 0;
// Driver program
int main()
{
int N;
Output:
292
Maximum Number of A's with 10 keystrokes is 20
Maximum Number of A's with 11 keystrokes is 27
Maximum Number of A's with 12 keystrokes is 36
Maximum Number of A's with 13 keystrokes is 48
Maximum Number of A's with 14 keystrokes is 64
Maximum Number of A's with 15 keystrokes is 81
Maximum Number of A's with 16 keystrokes is 108
Maximum Number of A's with 17 keystrokes is 144
Maximum Number of A's with 18 keystrokes is 192
Maximum Number of A's with 19 keystrokes is 256
Maximum Number of A's with 20 keystrokes is 324
The above function computes the same subproblems again and again. Recom-
putations of same subproblems can be avoided by storing the solutions to sub-
problems and solving problems in bottom up manner.
Below is Dynamic Programming based C implementation where an auxiliary
array screen[N] is used to store result of subproblems.
293
// Initialize length of optimal string for n keystrokes
screen[n-1] = 0;
return screen[N-1];
}
// Driver program
int main()
{
int N;
Output:
294
Maximum Number of A's with 9 keystrokes is 16
Maximum Number of A's with 10 keystrokes is 20
Maximum Number of A's with 11 keystrokes is 27
Maximum Number of A's with 12 keystrokes is 36
Maximum Number of A's with 13 keystrokes is 48
Maximum Number of A's with 14 keystrokes is 64
Maximum Number of A's with 15 keystrokes is 81
Maximum Number of A's with 16 keystrokes is 108
Maximum Number of A's with 17 keystrokes is 144
Maximum Number of A's with 18 keystrokes is 192
Maximum Number of A's with 19 keystrokes is 256
Maximum Number of A's with 20 keystrokes is 324
Thanks to Gaurav Saxena for providing the above approach to solve this
problem.
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above
Source
http://www.geeksforgeeks.org/how-to-print-maximum-number-of-a-using-given-four-keys/
Category: Misc Tags: Dynamic Programming
Post navigation
← CouponDunia Interview Experience | Set 2 (Fresher) Amazon Interview Ex-
perience | Set 179 (For SDE-1) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
295
Chapter 59
Initialize:
max_so_far = 0
max_ending_here = 0
Simple idea of the Kadane's algorithm is to look for all positive contiguous segments of the arr
max_so_far = max_ending_here = 0
296
C++
Python
max_so_far = 0
297
max_ending_here = 0
return max_so_far
Output:
Notes:
Algorithm doesn’t work for all negative numbers. It simply returns 0 if all
numbers are negative. For handling this we can add an extra phase before
actual implementation. The phase will look if all numbers are negative, if they
are it will return maximum of them (or smallest in terms of absolute value).
There may be other ways to handle it though.
Above program can be optimized further, if we compare max_so_far with
max_ending_here only if max_ending_here is greater than 0.
C++
298
max_ending_here = 0;
Python
def maxSubArraySum(a,size):
max_so_far = 0
max_ending_here = 0
return max_so_far
C++
#include<iostream>
using namespace std;
299
int maxSubArraySum(int a[], int size)
{
int max_so_far = a[0];
int curr_max = a[0];
Python
def maxSubArraySum(a,size):
max_so_far =a[0]
curr_max = a[0]
for i in range(1,size):
curr_max = max(a[i], curr_max + a[i])
max_so_far = max(max_so_far,curr_max)
return max_so_far
300
#This code is contributed by _Devesh Agrawal_
Output:
Source
http://www.geeksforgeeks.org/largest-sum-contiguous-subarray/
301
Chapter 60
Given a string, find the length of the longest substring without repeating char-
acters. For example, the longest substrings without repeating characters for
“ABDEFGABEF” are “BDEFGA” and “DEFGAB”, with length 6. For “BBBB”
the longest substring is “B”, with length 1. For “GEEKSFORGEEKS”, there
are two longest substrings shown in the below diagrams, with length 7.
The desired time complexity is O(n) where n is the length of the string.
302
Method 1 (Simple)
We can consider all substrings one by one and check for each substring whether
it contains all unique characters or not. There will be n*(n+1)/2 substrings.
Whether a substirng contains all unique characters or not can be checked in lin-
ear time by scanning it from left to right and keeping a map of visited characters.
Time complexity of this solution would be O(nˆ3).
Method 2 (Linear Time)
Let us talk about the linear time solution now. This solution uses extra space to
store the last indexes of already visited characters. The idea is to scan the string
from left to right, keep track of the maximum length Non-Repeating Character
Substring (NRCS) seen so far. Let the maximum length be max_len. When
we traverse the string, we also keep track of length of the current NRCS using
cur_len variable. For every new character, we look for it in already processed
part of the string (A temp array called visited[] is used for this purpose). If it
is not present, then we increase the cur_len by 1. If present, then there are two
cases:
a) The previous instance of character is not part of current NRCS (The NRCS
which is under process). In this case, we need to simply increase cur_len by 1.
b) If the previous instance is part of the current NRCS, then our current NRCS
changes. It becomes the substring staring from the next character of previous
instance to currently scanned character. We also need to compare cur_len and
max_len, before changing current NRCS (or changing cur_len).
Implementation
#include<stdlib.h>
#include<stdio.h>
#define NO_OF_CHARS 256
303
/* Mark first character as visited by storing the index of first
character in visited array. */
visited[str[0]] = 0;
cur_len = i - prev_index;
}
// Compare the length of last NRCS with max_len and update max_len if needed
if (cur_len > max_len)
max_len = cur_len;
return max_len;
}
304
/* Driver program to test above function */
int main()
{
char str[] = "ABDEFGABEF";
printf("The input string is %s \n", str);
int len = longestUniqueSubsttr(str);
printf("The length of the longest non-repeating character substring is %d", len);
getchar();
return 0;
}
Output
Source
http://www.geeksforgeeks.org/length-of-the-longest-substring-without-repeating-characters/
305
Chapter 61
Given a string ‘str’ of digits, find length of the longest substring of ‘str’, such
that the length of the substring is 2k digits and sum of left k digits is equal to
the sum of right k digits.
Examples:
306
// A simple C based program to find length of longest even length
// substring with same sum of digits in left and right
#include<stdio.h>
#include<string.h>
Output:
307
Length of the substring is 4
308
}
}
return maxlen;
}
Output:
Time complexity of the above solution is O(n2 ), but it requires O(n2 ) extra
space.
[A O(n2 ) and O(n) extra space solution]
The idea is to use a single dimensional array to store cumulative sum.
309
{
int j = i + len - 1;
Output:
310
{
/* For current midpoint 'i', keep expanding substring on
both sides, if sum of both sides becomes equal update
ans */
int l = i, r = i + 1;
Output:
311
Source
http://www.geeksforgeeks.org/longest-even-length-substring-sum-first-second-half/
Category: Strings Tags: Dynamic Programming
312
Chapter 62
Longest Palindromic
Substring | Set 1
Given a string, find the longest substring which is palindrome. For example, if
the given string is “forgeeksskeegfor”, the output should be “geeksskeeg”.
Method 1 ( Brute Force )
The simple approach is to check each substring whether the substring is a palin-
drome or not. We can run three loops, the outer two loops pick all substrings
one by one by fixing the corner characters, the inner loop checks whether the
picked substring is palindrome or not.
Time complexity: O ( nˆ3 )
Auxiliary complexity: O ( 1 )
Method 2 ( Dynamic Programming )
The time complexity can be reduced by storing results of subproblems. The
idea is similar to thispost. We maintain a boolean table[n][n] that is filled in
bottom up manner. The value of table[i][j] is true, if the substring is palindrome,
otherwise false. To calculate table[i][j], we first check the value of table[i+1][j-
1], if the value is true and str[i] is same as str[j], then we make table[i][j] true.
Otherwise, the value of table[i][j] is made false.
#include <stdio.h>
#include <string.h>
313
// A utility function to print a substring str[low..high]
void printSubStr( char* str, int low, int high )
{
for( int i = low; i <= high; ++i )
printf("%c", str[i]);
}
314
int j = i + k - 1;
if (k > maxLength)
{
start = i;
maxLength = k;
}
}
}
}
Output:
315
Source
http://www.geeksforgeeks.org/longest-palindrome-substring-set-1/
Category: Strings Tags: Dynamic Programming
316
Chapter 63
Longest Repeating
Subsequence
Given a string, find length of the longest repeating subseequence such that the
two subsequence don’t have same string character at same position, i.e., any i’th
character in the two subsequences shouldn’t have the same index in the original
string.
Examples:
317
This problem is just the modification of Longest Common Subsequence problem.
The idea is to find the LCS(str, str) where str is the input string with the
restriction that when both the characters are same, they shouldn’t be on the
same index in the two strings.
Below is C++ implementation of the idea.
// Driver Program
int main()
{
string str = "aabb";
cout << "The length of the largest subsequence that"
" repeats itself is : "
318
<< findLongestRepeatingSubSeq(str);
return 0;
}
Output:
This article is contributed by Ekta Goel. Please write comments if you find
anything incorrect, or you want to share more information about the topic
discussed above.
Source
http://www.geeksforgeeks.org/longest-repeating-subsequence/
Category: Strings Tags: Dynamic Programming
319
Chapter 64
In a daily share trading, a buyer buys shares in the morning and sells it on same
day. If the trader is allowed to make at most 2 transactions in a day, where as
second transaction can only start after first one is complete (Sell->buy->sell-
>buy). Given stock prices throughout day, find out maximum profit that a
share trader could have made.
Examples:
320
Not possible to earn.
Maximum possible using one transaction can be calculated using following O(n)
algorithm
Maximum difference between two elements such that larger element appears
after the smaller number
Time complexity of above simple solution is O(n2 ).
We can do this O(n) using following Efficient Solution. The idea is to store
maximum possible profit of every subarray and solve the problem in following
two phases.
1) Create a table profit[0..n-1] and initialize all values in it 0.
2) Traverse price[] from right to left and update profit[i] such that profit[i] stores
maximum profit achievable from one transaction in subarray price[i..n-1]
3) Traverse price[] from left to right and update profit[i] such that profit[i] stores
maximum profit such that profit[i] contains maximum achievable profit from two
transactions in subarray price[0..i].
4) Return profit[n-1]
To do step 1, we need to keep track of maximum price from right to left side
and to do step 2, we need to keep track of minimum price from left to right.
Why we traverse in reverse directions? The idea is to save space, in second
step, we use same array for both purposes, maximum with 1 transaction and
maximum with 2 transactions. After an iteration i, the array profit[0..i] contains
maximum profit with 2 transactions and profit[i+1..n-1] contains profit with two
transactions.
Below are implementations of above idea.
C++
321
// C++ program to find maximum possible profit with at most
// two transactions
#include<iostream>
using namespace std;
322
(price[i]-min_price) );
}
int result = profit[n-1];
return result;
}
// Drive program
int main()
{
int price[] = {2, 30, 15, 10, 8, 25, 80};
int n = sizeof(price)/sizeof(price[0]);
cout << "Maximum Profit = " << maxProfit(price, n);
return 0;
}
Python
if price[i]> max_price:
max_price = price[i]
323
# Get the maximum profit with two transactions allowed
# After this loop, profit[n-1] contains the result
min_price=price[0]
for i in range(1,n):
result = profit[n-1]
return result
# Driver function
price = [2, 30, 15, 10, 8, 25, 80]
print "Maximum profit is", maxProfit(price, len(price))
Output:
Source
http://www.geeksforgeeks.org/maximum-profit-by-buying-and-selling-a-share-at-most-twice/
324
Chapter 65
Given a binary matrix, find out the maximum size square sub-matrix with all
1s.
For example, consider the below binary matrix.
0 1 1 0 1
1 1 0 1 0
0 1 1 1 0
1 1 1 1 0
1 1 1 1 1
0 0 0 0 0
1 1 1
1 1 1
1 1 1
Algorithm:
Let the given binary matrix be M[R][C]. The idea of the algorithm is to construct
an auxiliary size matrix S[][] in which each entry S[i][j] represents size of the
square sub-matrix with all 1s including M[i][j] where M[i][j] is the rightmost and
bottommost entry in sub-matrix.
325
1) Construct a sum matrix S[R][C] for the given M[R][C].
a) Copy first row and first columns as it is from M[][] to S[][]
b) For other entries, use following expressions to construct S[][]
If M[i][j] is 1 then
S[i][j] = min(S[i][j-1], S[i-1][j], S[i-1][j-1]) + 1
Else /*If M[i][j] is 0*/
S[i][j] = 0
2) Find the maximum entry in S[R][C]
3) Using the value and coordinates of maximum entry in S[i], print
sub-matrix of M[][]
For the given M[R][C] in above example, constructed S[R][C] would be:
0 1 1 0 1
1 1 0 1 0
0 1 1 1 0
1 1 2 2 0
1 2 2 3 1
0 0 0 0 0
The value of maximum entry in above matrix is 3 and coordinates of the entry
are (4, 3). Using the maximum value and its coordinates, we can find out the
required sub-matrix.
#include<stdio.h>
#define bool int
#define R 6
#define C 5
326
for(j = 0; j < C; j++)
S[0][j] = M[0][j];
/* UTILITY FUNCTIONS */
/* Function to get minimum of three values */
int min(int a, int b, int c)
{
327
int m = a;
if (m > b)
m = b;
if (m > c)
m = c;
return m;
}
printMaxSubSquare(M);
getchar();
}
Source
http://www.geeksforgeeks.org/maximum-size-sub-matrix-with-all-1s-in-a-binary-matrix/
Category: Arrays Tags: Dynamic Programming
Post navigation
← Print list items containing all characters of a given word Inorder Tree Traver-
sal without Recursion →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
328
Chapter 66
Maximum weight
transformation of a given
string
Given a string consisting of only A’s and B’s. We can transform the given string
to another string by toggling any character. Thus many transformations of the
given string are possible. The task is to find Weight of the maximum weight
transformation.
Weight of a sting is calculated using below formula.
Examples:
329
Transformations of given string are "AA", "AB", "BA" and "BB".
Maximum weight transformation is "AB" or "BA". And weight
is "One Pair - One Toggle" = 4-1 = 3.
If (n == 1)
maxWeight(str[0..n-1]) = 1
If we draw the complete recursion tree, we can observer that many subproblems
are solved again and again. Since same suproblems are called again, this problem
has Overlapping Subprolems property. So min square sum problem has both
properties (see thisand this) of a dynamic programming problem. Like other
typical Dynamic Programming(DP) problems.
Below is a memoization based solution. A lookup table is used to see if a problem
is already computed.
330
// C++ program to find maximum weight transformation
// of a given string
#include<bits/stdc++.h>
using namespace std;
331
// Call recursive function
return getMaxRec(str, 0, str.length(), lookup);
}
// Driver program
int main()
{
string str = "AAAAABB";
cout << "Maximum weight of a transformation of "
<< str << " is " << getMaxWeight(str);
return 0;
}
Output:
Source
http://www.geeksforgeeks.org/maximum-weight-transformation-of-a-given-string/
Category: Strings Tags: Dynamic Programming
Post navigation
← SAP Labs Interview Experience | Set 11 (On-Campus) Bitmasking and Set
1 (Count ways to assign unique cap to every person) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
332
Chapter 67
Two triangulations of the same convex pentagon. The triangulation on the left
has a cost of 8 + 2√2 + 2√5 (approximately 15.30), the one on the right has a
cost of 4 + 2√2 + 4√5 (approximately 15.77).
This problem has recursive substructure. The idea is to divide the polygon into
three parts: a single triangle, the sub-polygon to the left, and the sub-polygon to
the right. We try all possible divisions like this and find the one that minimizes
the cost of the triangle plus the cost of the triangulation of the two sub-polygons.
333
Let Minimum Cost of triangulation of vertices from i to j be minCost(i, j)
If j
Following is C++ implementation of above naive recursive formula.
334
// Initialize result as infinite
double res = MAX;
Output:
15.3006
335
It can be easily seen in the above recursion tree that the problem has many over-
lapping subproblems. Since the problem has both properties: Optimal Substruc-
ture and Overlapping Subproblems, it can be efficiently solved using dynamic
programming.
Following is C++ implementation of dynamic programming solution.
336
// There must be at least 3 points to form a triangle
if (n < 3)
return 0;
// Fill table using above recursive formula. Note that the table
// is filled in diagonal fashion i.e., from diagonal elements to
// table[0][n-1] which is the result.
for (int gap = 0; gap < n; gap++)
{
for (int i = 0, j = gap; j < n; i++, j++)
{
if (j < i+2)
table[i][j] = 0.0;
else
{
table[i][j] = MAX;
for (int k = i+1; k < j; k++)
{
double val = table[i][k] + table[k][j] + cost(points,i,j,k);
if (table[i][j] > val)
table[i][j] = val;
}
}
}
}
return table[0][n-1];
}
Output:
337
15.3006
http://www.cs.utexas.edu/users/djimenez/utsa/cs3343/lecture12.html
http://www.cs.utoronto.ca/~heap/Courses/270F02/A4/chains/node2.html
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above
Source
http://www.geeksforgeeks.org/minimum-cost-polygon-triangulation/
Category: Misc Tags: Dynamic Programming, geometric algorithms
Post navigation
← D E Shaw Interview | Set 6 (Off-Campus) Find n’th number in a number
system with only 3 and 4 →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
338
Chapter 68
Given a grid with each cell consisting of positive, negative or no points i.e,
zero points. We can move across a cell only if we have positive points ( > 0 ).
Whenever we pass through a cell, points in that cell are added to our overall
points. We need to find minimum initial points to reach cell (m-1, n-1) from (0,
0).
Constraints :
339
greater than 0 points at the end).
• If points[i][j] == 0, then nothing is gained in this cell; the player can leave
the cell with the same points as he enters the room with, i.e. dp[i][j] =
min_Points_on_exit.
• If dp[i][j] If dp[i][j] > 0, then the player could enter (i, j) with points as
little as min_Points_on_exit – points[i][j]. since he could gain “points[i][j]”
points in this cell. However, the value of min_Points_on_exit – points[i][j]
might drop to 0 or below in this situation. When this happens, we must
clip the value to 1 in order to make sure dp[i][j] stays positive:
dp[i][j] = max(min_Points_on_exit – points[i][j], 1).
340
// C++ program to find minimum initial points to reach destination
#include<bits/stdc++.h>
#define R 3
#define C 3
using namespace std;
// Base case
dp[m-1][n-1] = points[m-1][n-1] > 0? 1:
abs(points[m-1][n-1]) + 1;
return dp[0][0];
}
// Driver Program
int main()
{
341
};
cout << "Minimum Initial Points Required: "
<< minInitialPoints(points);
return 0;
}
Output:
Source
http://www.geeksforgeeks.org/minimum-positive-points-to-reach-destination/
Category: Arrays Tags: Dynamic Programming, Matrix
Post navigation
← Amazon Interview Experience | Set 227 (On-Campus for Internship and Full-
Time) Count of n digit numbers whose sum of digits equals to given sum →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
342
Chapter 69
Given an array of integers where each element represents the max number of
steps that can be made forward from that element. Write a function to return
the minimum number of jumps to reach the end of the array (starting from the
first element). If an element is 0, then cannot move through that element.
Example:
#include <stdio.h>
#include <limits.h>
343
// Returns minimum number of jumps to reach arr[h] from arr[l]
int minJumps(int arr[], int l, int h)
{
// Base case: when source and destination are same
if (h == l)
return 0;
return min;
}
If we trace the execution of this method, we can see that there will be overlapping
subproblems. For example, minJumps(3, 9) will be called two times as arr[3] is
reachable from arr[1] and arr[2]. So this problem has both properties (optimal
substructure and overlapping subproblems) of Dynamic Programming.
Method 2 (Dynamic Programming)
In this method, we build a jumps[] array from left to right such that jumps[i]
indicates the minimum number of jumps needed to reach arr[i] from arr[0]. Fi-
nally, we return jumps[n-1].
344
#include <stdio.h>
#include <limits.h>
if (n == 0 || arr[0] == 0)
return INT_MAX;
jumps[0] = 0;
Output:
345
Minimum number of jumps to reach end is 3
int i, j;
346
// takes the minimum
for (j = i+1; j < n && j <= arr[i] + i; j++)
{
if (min > jumps[j])
min = jumps[j];
}
// Handle overflow
if (min != INT_MAX)
jumps[i] = min + 1;
else
jumps[i] = min; // or INT_MAX
}
}
return jumps[0];
}
Source
http://www.geeksforgeeks.org/minimum-number-of-jumps-to-reach-end-of-a-given-array/
Category: Arrays Tags: Dynamic Programming
Post navigation
← Count smaller elements on right side Populate Inorder Successor for all nodes
→
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
347
Chapter 70
Minimum number of
squares whose sum equals
to given number n
Input: n = 100
Output: 1
100 can be written as 102. Note that 100 can also be
written as 52 + 52 + 52 + 52, but this
representation requires 4 squares.
Input: n = 6
Output: 3
348
If n = 1 and x*x
Below is a simple recursive solution based on above recursive formula.
// Driver program
int main()
{
cout << getMinSquares(6);
return 0;
}
Output:
349
The time complexity of above solution is exponential. If we draw the complete
recursion tree, we can observer that many subproblems are solved again and
again. For example, when we start from n = 6, we can reach 4 by subtracting
one 2 times and by subtracting 2 one times. So the subproblem for 4 is called
twice.
Since same suproblems are called again, this problem has Overlapping Subpro-
lems property. So min square sum problem has both properties (see thisand
this) of a dynamic programming problem. Like other typical Dynamic Pro-
gramming(DP) problems, recomputations of same subproblems can be avoided
by constructing a temporary array table[][] in bottom up manner. Below is
Dynamic Programming based solution
350
}
}
return res;
}
// Driver program
int main()
{
cout << getMinSquares(6);
return 0;
}
Output:
Source
http://www.geeksforgeeks.org/minimum-number-of-squares-whose-sum-equals-to-given-number-n/
Category: Misc Tags: Dynamic Programming, MathematicalAlgo
351
Chapter 71
………………………………
352
………………………………
We need to print the count of possible numbers.
We strongly recommend to minimize the browser and try this yourself
first.
N = 1 is trivial case, number of possible numbers would be 10 (0, 1, 2, 3, …., 9)
For N > 1, we need to start from some button, then move to any of the four
direction (up, left, right or down) which takes to a valid button (should not
go to *, #). Keep doing this until N length number is obtained (depth first
traversal).
Recursive Solution:
Mobile Keypad is a rectangular grid of 4X3 (4 rows and 3 columns)
Lets say Count(i, j, N) represents the count of N length numbers starting from
position (i, j)
If N = 1
Count(i, j, N) = 10
Else
Count(i, j, N) = Sum of all Count(r, c, N-1) where (r, c) is new
position after valid move of length 1 from current
position (i, j)
353
return 1;
return totalCount;
}
354
}
return 0;
}
Output:
Dynamic Programming
There are many repeated traversal on smaller paths (traversal for smaller N) to
find all possible longer paths (traversal for bigger N). See following two diagrams
for example. In this traversal, for N = 4 from two starting positions (buttons
‘4’ and ‘8’), we can see there are few repeated traversals for N = 2 (e.g. 4 -> 1,
6 -> 3, 8 -> 9, 8 -> 7 etc).
355
Since the problem has both properties: Optimal Substructure and Overlapping
Subproblems, it can be efficiently solved using dynamic programming.
Following is C program for dynamic programming implementation.
356
int getCount(char keypad[][3], int n)
{
if(keypad == NULL || n <= 0)
return 0;
if(n == 1)
return 10;
357
{
ro = i + row[move];
co = j + col[move];
if (ro >= 0 && ro <= 3 && co >=0 && co <= 2 &&
keypad[ro][co] != '*' && keypad[ro][co] != '#')
{
nextNum = keypad[ro][co] - '0';
count[num][k] += count[nextNum][k-1];
}
}
}
}
}
}
return 0;
}
Output:
358
Count for numbers of length 3: 138
Count for numbers of length 4: 532
Count for numbers of length 5: 2062
359
even[1] = odd[1] + odd[2] + odd[4];
even[2] = odd[2] + odd[1] + odd[3] + odd[5];
even[3] = odd[3] + odd[2] + odd[6];
even[4] = odd[4] + odd[1] + odd[5] + odd[7];
even[5] = odd[5] + odd[2] + odd[4] + odd[8] + odd[6];
even[6] = odd[6] + odd[3] + odd[5] + odd[9];
even[7] = odd[7] + odd[4] + odd[8];
even[8] = odd[8] + odd[0] + odd[5] + odd[7] + odd[9];
even[9] = odd[9] + odd[6] + odd[8];
}
else
{
odd[0] = even[0] + even[8];
odd[1] = even[1] + even[2] + even[4];
odd[2] = even[2] + even[1] + even[3] + even[5];
odd[3] = even[3] + even[2] + even[6];
odd[4] = even[4] + even[1] + even[5] + even[7];
odd[5] = even[5] + even[2] + even[4] + even[8] + even[6];
odd[6] = even[6] + even[3] + even[5] + even[9];
odd[7] = even[7] + even[4] + even[8];
odd[8] = even[8] + even[0] + even[5] + even[7] + even[9];
odd[9] = even[9] + even[6] + even[8];
}
}
360
{'7','8','9'},
{'*','0','#'}
};
printf("Count for numbers of length %d: %d\n", 1, getCount(keypad, 1));
printf("Count for numbers of length %d: %d\n", 2, getCount(keypad, 2));
printf("Count for numbers of length %d: %d\n", 3, getCount(keypad, 3));
printf("Count for numbers of length %d: %d\n", 4, getCount(keypad, 4));
printf("Count for numbers of length %d: %d\n", 5, getCount(keypad, 5));
return 0;
}
Output:
Source
http://www.geeksforgeeks.org/mobile-numeric-keypad-problem/
Category: Misc Tags: Dynamic Programming, Matrix
Post navigation
← Comparison of Autoboxed Integer objects in Java Arista Networks Interview
| Set 3 →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
361
Chapter 72
Given a matrix where every cell has some number of coins. Count number of
ways to reach bottom right from top left with exactly k coins. We can move to
(i+1, j) and (i, j+1) from a cell (i, j).
Example:
Input: k = 12
mat[][] = { {1, 2, 3},
{4, 6, 5},
{3, 2, 1}
};
Output: 2
There are two paths with 12 coins
1 -> 2 -> 6 -> 2 -> 1
1 -> 2 -> 3 -> 5 -> 1
362
If (m == 0 and n == 0)
return 1 if mat[0][0] == k else return 0
Else:
pathCount(m, n, k) = pathCount(m-1, n, k - mat[m][n]) +
pathCount(m, n-1, k - mat[m][n])
// Driver program
int main()
{
int k = 12;
int mat[R][C] = { {1, 2, 3},
{4, 6, 5},
{3, 2, 1}
363
};
cout << pathCount(mat, k);
return 0;
}
Output:
The time complexity of above solution recursive is exponential. We can solve this
problem in Pseudo Polynomial Time (time complexity is dependent on numeric
value of input) using Dynamic Programming. The idea is to use a 3 dimensional
table dp[m][n][k] where m is row number, n is column number and k is number
of coins. Below is Dynamic Programming based C++ implementation.
int dp[R][C][MAX_K];
return dp[m][n][k];
}
364
// This function mainly initializes dp[][][] and calls
// pathCountDPRecDP()
int pathCountDP(int mat[][C], int k)
{
memset(dp, -1, sizeof dp);
return pathCountDPRecDP(mat, R-1, C-1, k);
}
Output:
Source
http://www.geeksforgeeks.org/number-of-paths-with-exactly-k-coins/
Category: Arrays Tags: Dynamic Programming, Matrix
Post navigation
← Treap | Set 2 (Implementation of Search, Insert and Delete) Iterative Depth
First Traversal of Graph →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
365
Chapter 73
The Fibonacci numbers are the numbers in the following integer sequence.
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 141, ……..
In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the
recurrence relation
Fn = Fn-1 + Fn-2
F0 = 0 and F1 = 1.
Write a function int fib(int n) that returns Fn . For example, if n = 0, then fib()
should return 0. If n = 1, then it should return 1. For n > 1, it should return
Fn-1 + Fn-2
Following are different methods to get the nth Fibonacci number.
Method 1 ( Use recursion )
A simple method that is a direct recusrive implementation mathematical recu-
rance relation given above.
366
#include<stdio.h>
int fib(int n)
{
if (n <= 1)
return n;
return fib(n-1) + fib(n-2);
}
int main ()
{
int n = 9;
printf("%d", fib(n));
getchar();
return 0;
}
fib(5)
/ \
fib(4) fib(3)
/ \ / \
fib(3) fib(2) fib(2) fib(1)
/ \ / \ / \
fib(2) fib(1) fib(1) fib(0) fib(1) fib(0)
/ \
fib(1) fib(0)
Extra Space: O(n) if we consider the function call stack size, otherwise O(1).
Method 2 ( Use Dynamic Programming )
We can avoid the repeated work done is the method 1 by storing the Fibonacci
numbers calculated so far.
#include<stdio.h>
367
int fib(int n)
{
/* Declare an array to store Fibonacci numbers. */
int f[n+1];
int i;
return f[n];
}
int main ()
{
int n = 9;
printf("%d", fib(n));
getchar();
return 0;
}
#include<stdio.h>
int fib(int n)
{
int a = 0, b = 1, c, i;
if( n == 0)
return a;
for (i = 2; i <= n; i++)
368
{
c = a + b;
a = b;
b = c;
}
return b;
}
int main ()
{
int n = 9;
printf("%d", fib(n));
getchar();
return 0;
}
#include <stdio.h>
/* Helper function that calculates F[][] raise to the power n and puts the
result in F[][]
Note that this function is desinged only for fib() and won't work as general
power function */
369
void power(int F[2][2], int n);
int fib(int n)
{
int F[2][2] = {{1,1},{1,0}};
if (n == 0)
return 0;
power(F, n-1);
return F[0][0];
}
F[0][0] = x;
F[0][1] = y;
F[1][0] = z;
F[1][1] = w;
}
370
Time Complexity: O(n)
Extra Space: O(1)
Method 5 ( Optimized Method 4 )
The method 4 can be optimized to work in O(Logn) time complexity. We can
do recursive multiplication to get power(M, n) in the prevous method (Similar
to the optimization done in thispost)
#include <stdio.h>
power(F, n/2);
multiply(F, F);
if (n%2 != 0)
multiply(F, M);
}
371
F[0][0] = x;
F[0][1] = y;
F[1][0] = z;
F[1][1] = w;
}
Source
http://www.geeksforgeeks.org/program-for-nth-fibonacci-number/
372
Chapter 74
Catalan numbers are a sequence of natural numbers that occurs in many inter-
esting counting problems like following.
1) Count the number of expressions containing n pairs of parentheses which
are correctly matched. For n = 3, possible expressions are ((())), ()(()), ()()(),
(())(), (()()).
2) Count the number of possible Binary Search Trees with n keys (See this)
3) Count the number of full binary trees (A rooted binary tree is full if every
vertex has either two children or no children) with n+1 leaves.
See thisfor more applications.
The first few Catalan numbers for n = 0, 1, 2, 3, … are 1, 1, 2, 5, 14, 42, 132,
429, 1430, 4862, …
Recursive Solution
Catalan numbers satisfy the following recursive formula.
#include<iostream>
using namespace std;
373
unsigned long int catalan(unsigned int n)
{
// Base case
if (n <= 1) return 1;
return res;
}
Output :
The value of nth catalan number is exponential that makes the time complexity
exponential.
Dynamic Programming Solution
We can observe that the above recursive implementation does a lot of repeated
work (we can the same by drawing recursion tree). Since there are overlapping
subproblems, we can use dynamic programming for this. Following is a Dynamic
programming based implementation in C++.
#include<iostream>
using namespace std;
374
// A dynamic programming based function to find nth
// Catalan number
unsigned long int catalanDP(unsigned int n)
{
// Table to store results of subproblems
unsigned long int catalan[n+1];
Output:
375
We have discussed aO(n) approach to find binomial coefficient nCr.
#include<iostream>
using namespace std;
return res;
}
// return 2nCn/(n+1)
return c/(n+1);
}
376
Output:
References:
http://en.wikipedia.org/wiki/Catalan_number
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above
Source
http://www.geeksforgeeks.org/program-nth-catalan-number/
377
Chapter 75
Given an unsorted array, trim the array such that twice of minimum is greater
than maximum in the trimmed array. Elements should be removed either end
of the array.
Number of removals should be minimum.
Examples:
arr[] = {4, 7, 5, 6}
Output: 0
We don't need to remove any element as
4*2 > 7 (Note that min = 4, max = 8)
arr[] = {20, 7, 5, 6}
Output: 1
We need to remove 20 so that 2*min becomes
378
more than max
arr[] = {20, 4, 1, 3}
Output: 3
We need to remove any three elements from ends
like 20, 4, 1 or 4, 1, 3 or 20, 3, 1 or 20, 4, 1
Naive Solution:
A naive solution is to try every possible case using recurrence. Following is
the naive recursive algorithm. Note that the algorithm only returns minimum
numbers of removals to be made, it doesn’t print the trimmed array. It can be
easily modified to print the trimmed array as well.
#include <iostream>
using namespace std;
379
int max(int arr[], int l, int h)
{
int mx = arr[l];
for (int i=l+1; i<=h; i++)
if (mx < arr[i])
mx = arr[i];
return mx;
}
Output:
380
4
#include <iostream>
using namespace std;
381
// in arr[l..h] so that 2*min becomes greater than max.
int minRemovalsDP(int arr[], int n)
{
// Create a table to store solutions of subproblems
int table[n][n], gap, i, j, mn, mx;
// Fill table using above recursive formula. Note that the table
// is filled in diagonal fashion (similar to http://goo.gl/PQqoS),
// from diagonal elements to table[0][n-1] which is the result.
for (gap = 0; gap < n; ++gap)
{
for (i = 0, j = gap; j < n; ++i, ++j)
{
mn = min(arr, i, j);
mx = max(arr, i, j);
table[i][j] = (2*mn > mx)? 0: min(table[i][j-1]+1,
table[i+1][j]+1);
}
}
return table[0][n-1];
}
382
chooses ending point for the current starting point. We keep track of longest
subarray with the given property.
Following is C++ implementation of the above approach. Thanks to Richard
Zhang for suggesting this solution.
383
}
}
This article is contributed by Rahul Jain. Please write comments if you find
anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/remove-minimum-elements-either-side-2min-max/
Category: Arrays Tags: Dynamic Programming
Post navigation
← Fab.com Pune Interview | Set 2 Amazon Interview | Set 80 →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
384
Chapter 76
Shortest Common
Supersequence
Given two strings str1 and str2, find the shortest string that has both str1 and
str2 as subsequences.
Examples:
385
How does this work?
We need to find a string that has both strings as subsequences and is shortest
such string. If both strings have all characters different, then result is sum of
lengths of two given strings. If there are common characters, then we don’t
want them multiple times as the task is to minimize length. Therefore, we fist
find the longest common subsequence, take one occurrence of this subsequence
and add extra characters.
386
/* Following steps build L[m+1][n+1] in bottom up fashion.
Note that L[i][j] contains length of LCS of X[0..i-1]
and Y[0..j-1] */
for (i=0; i<=m; i++)
{
for (j=0; j<=n; j++)
{
if (i == 0 || j == 0)
L[i][j] = 0;
else
L[i][j] = max(L[i-1][j], L[i][j-1]);
}
}
Output:
387
Let X[0..m-1] and Y[0..n-1] be two strings and m and be respective
lengths.
if (m == 0) return n;
if (n == 0) return m;
if (X[m-1] == Y[n-1])
return 1 + superSeq(X, Y, m-1, n-1);
388
return 0;
}
Output:
Time complexity of the above solution exponential O(2min(m, n) ). Since there are
overlapping subproblems, we can efficiently solve this recursive problem using
Dynamic Programming. Below is Dynamic Programming based implementation.
Time complexity of this solution is O(mn).
return dp[m][n];
}
389
// Driver program to test above function
int main()
{
char X[] = "AGGTAB";
char Y[] = "GXTXAYB";
cout << "Length of the shortest supersequence is "
<< superSeq(X, Y, strlen(X), strlen(Y));
return 0;
}
Output:
Source
http://www.geeksforgeeks.org/shortest-common-supersequence/
Category: Strings Tags: Dynamic Programming
Post navigation
← Count BST subtrees that lie in given range Shortest Superstring Problem →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
390
Chapter 77
Given a directed and two vertices ‘u’ and ‘v’ in it, find shortest path from ‘u’
to ‘v’ with exactly k edges on the path.
The graph is given as adjacency matrix representation where value of graph[i][j]
indicates the weight of an edge from vertex i to vertex j and a value INF(infinite)
indicates no edge from i to j.
For example consider the following graph. Let source ‘u’ be vertex 0, destination
‘v’ be 3 and k be 2. There are two walks of length 2, the walks are {0, 2, 3} and
{0, 1, 3}. The shortest among the two is {0, 2, 3} and weight of path is 3+6 =
9.
391
The idea is to browse through all paths of length k from u to v using the
approach discussed in the previous post and return weight of the shortest path.
A simple solution is to start from u, go to all adjacent vertices and recur for
adjacent vertices with k as k-1, source as adjacent vertex and destination as v.
Following is C++ implementation of this simple solution.
// Initialize result
int res = INF;
392
for (int i = 0; i < V; i++)
{
if (graph[u][i] != INF && u != i && v != i)
{
int rec_res = shortestPath(graph, i, v, k-1);
if (rec_res != INF)
res = min(res, graph[u][i] + rec_res);
}
}
return res;
}
Output:
The worst case time complexity of the above function is O(Vk ) where V is
the number of vertices in the given graph. We can simply analyze the time
complexity by drawing recursion tree. The worst occurs for a complete graph. In
worst case, every internal node of recursion tree would have exactly V children.
We can optimize the above solution using Dynamic Programming. The
idea is to build a 3D table where first dimension is source, second dimension is
destination, third dimension is number of edges from source to destination, and
the value is count of walks. Like other Dynamic Programming problems, we fill
the 3D table in bottom up manner.
393
// Dynamic Programming based C++ program to find shortest path with
// exactly k edges
#include <iostream>
#include <climits>
using namespace std;
394
}
}
}
}
return sp[u][v][k];
}
Output:
Time complexity of the above DP based solution is O(V3 K) which is much better
than the naive solution.
This article is contributed by Abhishek. Please write comments if you find
anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/shortest-path-exactly-k-edges-directed-weighted-graph/
Category: Graph Tags: Dynamic Programming
Post navigation
← Connect n ropes with minimum cost Tarjan’s Algorithm to find Strongly
Connected Components →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
395
Chapter 78
Tiling Problem
Given a “2 x n” board and tiles of size “2 x 1�, count the number of ways to tile
the given board using the 2 x 1 tiles. A tile can either be placed horizontally
i.e., as a 1 x 2 tile or vertically i.e., as 2 x 1 tile.
Examples:
Input n = 3
Output: 3
Explanation:
We need 3 tiles to tile the board of size 2 x 3.
We can tile the board using following ways
1) Place all 3 tiles vertically.
2) Place first tile vertically and remaining 2 tiles horizontally.
3) Place first 2 tiles horizontally and remaining tiles vertically
Input n = 4
Output: 5
Explanation:
For a 2 x 4 board, there are 5 ways
1) All 4 vertical
2) All 4 horizontal
3) First 2 vertical, remaining 2 horizontal
4) First 2 horizontal, remaining 2 vertical
5) Corner 2 vertical, middle 2 horizontal
396
We strongly recommend you to minimize your browser and try this
yourself first.
Let “count(n)” be the count of ways to place tiles on a “2 x n” grid, we have
following two ways to place first tile.
1) If we place first tile vertically, the problem reduces to “count(n-1)”
2) If we place first tile horizontally, we have to place second tile also horizontally.
So the problem reduces to “count(n-2)”
Therefore, count(n) can be written as below.
count(n) = n if n = 1 or n = 2
count(n) = count(n-1) + count(n-2)
The above recurrence is noting but Fibonacci Number expression. We can find
n’th Fibonacci number in O(Log n) time, see below for all method to find n’th
Fibonacci Number.
Different methods for n’th Fibonacci Number.
This article is contributed by Saurabh Jain. Please write comments if you find
anything incorrect, or you want to share more information about the topic
discussed above
397
Source
http://www.geeksforgeeks.org/tiling-problem/
Category: Misc Tags: Dynamic Programming, MathematicalAlgo
398
Chapter 79
Total number of
non-decreasing numbers
with n digits
A number is non-decreasing if every digit (except the first one) is greater than
or equal to previous digit. For example, 223, 4455567, 899, are non-decreasing
numbers.
So, given the number of digits n, you are required to find the count of total
non-decreasing numbers with n digits.
Examples:
Input: n = 1
Output: count = 10
Input: n = 2
Output: count = 55
Input: n = 3
Output: count = 220
399
so on. How to get count ending with a particular digit? We can recur for n-1
length and digits smaller than or equal to the last digit. So below is recursive
formula.
Count of n digit numbers = (Count of (n-1) digit numbers Ending with digit 9) +
(Count of (n-1) digit numbers Ending with digit 8) +
.............................................+
.............................................+
(Count of (n-1) digit numbers Ending with digit 0)
400
// Compute total numbers of non decreasing
// numbers of length 'len'
for (int len = 2; len <= n; len++)
{
// sum of all numbers of length of len-1
// in which last digit x is <= 'digit'
for (int x = 0; x <= digit; x++)
dp[digit][len] += dp[x][len-1];
}
}
return count;
}
// Driver program
int main()
{
int n = 3;
cout << countNonDecreasing(n);
return 0;
}
Output:
220
401
Below is a C++ program to compute count using above formula.
return count;
}
// Driver program
int main()
{
int n = 3;
cout << countNonDecreasing(n);
return 0;
}
Output:
220
402
Let us try for different values of n.
For general n digit case, we can apply Mathematical Induction. The count
would be equal to count n-1 digit beginning with 0, i.e., N*(N+1)/2*(N+2)/3*
….*(N+n-1-1)/(n-1). Plus count of n-1 digit numbers beginning with 1, i.e.,
(N-1)*(N)/2*(N+1)/3* ….*(N-1+n-1-1)/(n-1) (Note that N is replaced by N-1)
and so on.
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above
Source
http://www.geeksforgeeks.org/total-number-of-non-decreasing-numbers-with-n-digits/
Category: Misc Tags: Dynamic Programming
Post navigation
← Barracuda Networks Interview Experience HP R&D Interview Experience
(On-Campus, full time) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
403
Chapter 80
Travelling Salesman
Problem | Set 1 (Naive and
Dynamic Programming)
404
For example, consider the graph shown in figure on right side. A TSP tour in
the graph is 1-2-4-3-1. The cost of the tour is 10+25+30+15 which is 80.
The problem is a famous NP hardproblem. There is no polynomial time know
solution for this problem.
Following are different solutions for the traveling salesman problem.
Naive Solution:
1) Consider city 1 as the starting and ending point.
2) Generate all (n-1)! Permutationsof cities.
3) Calculate cost of every permutation and keep track of minimum cost permu-
tation.
4) Return the permutation with minimum cost.
Time Complexity: Ω(n!)
Dynamic Programming:
Let the given set of vertices be {1, 2, 3, 4,….n}. Let us consider 1 as starting
and ending point of output. For every other vertex i (other than 1), we find the
minimum cost path with 1 as the starting point, i as the ending point and all
vertices appearing exactly once. Let the cost of this path be cost(i), the cost of
corresponding Cycle would be cost(i) + dist(i, 1) where dist(i, 1) is the distance
from i to 1. Finally, we return the minimum of all [cost(i) + dist(i, 1)] values.
This looks simple so far. Now the question is how to get cost(i)?
To calculate cost(i) using Dynamic Programming, we need to have some recur-
405
sive relation in terms of sub-problems. Let us define a term C(S, i) be the cost
of the minimum cost path visiting each vertex in set S exactly once, starting at
1 and ending at i.
We start with all subsets of size 2 and calculate C(S, i) for all subsets where S is
the subset, then we calculate C(S, i) for all subsets S of size 3 and so on. Note
that 1 must be present in every subset.
For a set of size n, we consider n-2 subsets each of size n-1 such that all subsets
don’t have nth in them.
Using the above recurrence relation, we can write dynamic programming based
solution. There are at most O(n*2n ) subproblems, and each one takes linear time
to solve. The total running time is therefore O(n2 *2n ). The time complexity is
much less than O(n!), but still exponential. Space required is also exponential.
So this approach is also infeasible even for slightly higher number of vertices.
We will soon be discussing approximate algorithms for travelling salesman prob-
lem.
References:
http://www.lsi.upc.edu/~mjserna/docencia/algofib/P07/dynprog.pdf
http://www.cs.berkeley.edu/~vazirani/algorithms/chap6.pdf
Please write comments if you find anything incorrect, or you want to share more
information about the topic discussed above
Source
http://www.geeksforgeeks.org/travelling-salesman-problem-set-1/
406
Chapter 81
Ugly Numbers
Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, …
shows the first 11 ugly numbers. By convention, 1 is included.
Write a program to find and print the 150’th ugly number.
METHOD 1 (Simple)
Thanks to Nedylko Draganov for suggesting this solution.
Algorithm:
Loop for all positive integers until ugly number count is smaller than n, if an
integer is ugly than increment ugly number count.
To check if a number is ugly, divide the number by greatest divisible powers of
2, 3 and 5, if the number becomes 1 then it is an ugly number otherwise not.
For example, let us see how to check for 300 is ugly or not. Greatest divisible
power of 2 is 4, after dividing 300 by 4 we get 75. Greatest divisible power of 3
is 3, after dividing 75 by 3 we get 25. Greatest divisible power of 5 is 25, after
dividing 25 by 25 we get 1. Since we get 1 finally, 300 is ugly number.
Implementation:
# include<stdio.h>
# include<stdlib.h>
407
while (a%b == 0)
a = a/b;
return a;
}
This method is not time efficient as it checks for all integers until ugly number
count becomes n, but space complexity of this method is O(1)
408
METHOD 2 (Use Dynamic Programming)
Here is a time efficient solution with O(n) extra space. The ugly-number se-
quence is 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, …
because every number can only be divided by 2, 3, 5, one way to look at the
sequence is to split the sequence to three groups as below:
(1) 1×2, 2×2, 3×2, 4×2, 5×2, …
(2) 1×3, 2×3, 3×3, 4×3, 5×3, …
(3) 1×5, 2×5, 3×5, 4×5, 5×5, …
We can find that every subsequence is the ugly-sequence itself (1, 2, 3, 4,
5, …) multiply 2, 3, 5. Then we use similar merge method as merge sort, to
get every ugly number from the three subsequence. Every step we choose the
smallest one, and move one step after.
Algorithm:
initialize
ugly[] = | 1 |
i2 = i3 = i5 = 0;
First iteration
ugly[1] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
= Min(2, 3, 5)
= 2
ugly[] = | 1 | 2 |
i2 = 1, i3 = i5 = 0 (i2 got incremented )
Second iteration
ugly[2] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
= Min(4, 3, 5)
409
= 3
ugly[] = | 1 | 2 | 3 |
i2 = 1, i3 = 1, i5 = 0 (i3 got incremented )
Third iteration
ugly[3] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
= Min(4, 6, 5)
= 4
ugly[] = | 1 | 2 | 3 | 4 |
i2 = 2, i3 = 1, i5 = 0 (i2 got incremented )
Fourth iteration
ugly[4] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
= Min(6, 6, 5)
= 5
ugly[] = | 1 | 2 | 3 | 4 | 5 |
i2 = 2, i3 = 1, i5 = 1 (i5 got incremented )
Fifth iteration
ugly[4] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
= Min(6, 6, 10)
= 6
ugly[] = | 1 | 2 | 3 | 4 | 5 | 6 |
i2 = 3, i3 = 2, i5 = 1 (i2 and i3 got incremented )
# include<stdio.h>
# include<stdlib.h>
# define bool int
410
*(ugly+0) = 1;
411
unsigned no = getNthUglyNo(150);
printf("%dth ugly no. is %d ", 150, no);
getchar();
return 0;
}
Source
http://www.geeksforgeeks.org/ugly-numbers/
Category: Misc Tags: Dynamic Programming
Post navigation
← Output of C Programs | Set 4 Little and Big Endian Mystery →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
412
Chapter 82
A vertex cover of an undirected graph is a subset of its vertices such that for
every edge (u, v) of the graph, either ‘u’ or ‘v’ is in vertex cover. Although the
name is Vertex Cover, the set covers all edges of the given graph.
The problem to find minimum size vertex cover of a graph is NP complete. But
it can be solved in polynomial time for trees. In this post a solution for Binary
Tree is discussed. The same solution can be extended for n-ary trees.
For example, consider the following binary tree. The smallest vertex cover is
{20, 50, 30} and size of the vertex cover is 3.
413
The idea is to consider following two possibilities for root and recursively for all
nodes down the root.
1) Root is part of vertex cover: In this case root covers all children edges.
We recursively calculate size of vertex covers for left and right subtrees and add
1 to the result (for root).
2) Root is not part of vertex cover: In this case, both children of root must
be included in vertex cover to cover all root to children edges. We recursively
calculate size of vertex covers of all grandchildren and number of children to the
result (for two children of root).
Below is C implementation of above idea.
/* A binary tree node has data, pointer to left child and a pointer to
right child */
struct node
{
414
int data;
struct node *left, *right;
};
415
root->left->right->right = newNode(14);
root->right = newNode(22);
root->right->right = newNode(25);
return 0;
}
Output:
/* A binary tree node has data, pointer to left child and a pointer to
right child */
struct node
{
int data;
416
int vc;
struct node *left, *right;
};
// A memoization based function that returns size of the minimum vertex cover.
int vCover(struct node *root)
{
// The size of minimum vertex cover is zero if tree is empty or there
// is only one node
if (root == NULL)
return 0;
if (root->left == NULL && root->right == NULL)
return 0;
return root->vc;
}
417
int main()
{
// Let us construct the tree given in the above diagram
struct node *root = newNode(20);
root->left = newNode(8);
root->left->left = newNode(4);
root->left->right = newNode(12);
root->left->right->left = newNode(10);
root->left->right->right = newNode(14);
root->right = newNode(22);
root->right->right = newNode(25);
return 0;
}
Output:
References:
http://courses.csail.mit.edu/6.006/spring11/lectures/lec21.pdf
Exercise:
Extend the above solution for n-ary trees.
This article is contributed by Udit Gupta. Please write comments if you
find anything incorrect, or you want to share more information about the topic
discussed above
Source
http://www.geeksforgeeks.org/vertex-cover-problem-set-2-dynamic-programming-solution-tree/
418
Chapter 83
Given N jobs where every job is represented by following three elements of it.
1) Start Time
2) Finish Time.
3) Profit or Value Associated.
Find the maximum profit subset of jobs such that no two jobs in the subset
overlap.
Example:
A simple version of this problem is discussed herewhere every job has same profit
or value. The Greedy Strategy for activity selection doesn’t work here as the
longer schedule may have smaller profit or value.
The above problem can be solved using following recursive solution.
419
2) Now apply following recursive process.
// Here arr[] is array of n jobs
findMaximumProfit(arr[], n)
{
a) if (n == 1) return arr[0];
b) Return the maximum of following two profits.
(i) Maximum profit by excluding current job, i.e.,
findMaximumProfit(arr, n-1)
(ii) Maximum profit by including the current job
}
// C++ program for weighted job scheduling using Naive Recursive Method
#include <iostream>
#include <algorithm>
using namespace std;
420
int latestNonConflict(Job arr[], int i)
{
for (int j=i-1; j>=0; j--)
{
if (arr[j].finish <= arr[i-1].start)
return j;
}
return -1;
}
// Driver program
int main()
{
Job arr[] = {{3, 10, 20}, {1, 2, 50}, {6, 19, 100}, {2, 100, 200}};
int n = sizeof(arr)/sizeof(arr[0]);
cout << "The optimal profit is " << findMaxProfit(arr, n);
421
return 0;
}
Output:
The above solution may contain many overlapping subproblems. For example
if lastNonConflicting() always returns previous job, then findMaxProfitRec(arr,
n-1) is called twice and the time complexity becomes O(n*2n ). As another ex-
ample when lastNonConflicting() returns previous to previous job, there are two
recursive calls, for n-2 and n-1. In this example case, recursion becomes same
as Fibonacci Numbers.
So this problem has both properties of Dynamic Programming, Optimal Sub-
structureand Overlapping Subproblems.
Like other Dynamic Programming Problems, we can solve this problem by mak-
ing a table that stores solution of subproblems.
Below is C++ implementation based on Dynamic Programming.
422
for (int j=i-1; j>=0; j--)
{
if (arr[j].finish <= arr[i].start)
return j;
}
return -1;
}
return result;
}
// Driver program
int main()
{
Job arr[] = {{3, 10, 20}, {1, 2, 50}, {6, 19, 100}, {2, 100, 200}};
int n = sizeof(arr)/sizeof(arr[0]);
cout << "The optimal profit is " << findMaxProfit(arr, n);
423
return 0;
}
Output:
http://courses.cs.washington.edu/courses/cse521/13wi/slides/06dp-sched.pdf
This article is contributed by Shivam. Please write comments if you find any-
thing incorrect, or you want to share more information about the topic discussed
above
Source
http://www.geeksforgeeks.org/weighted-job-scheduling/
Category: Arrays Tags: Dynamic Programming
Post navigation
← Optimal read list for given number of days Housing.com Interview Experience
| Set 3 (On-Campus) →
Writing code in comment? Please use code.geeksforgeeks.org, generate link and
share the link here.
424