Download - Dynamic Programming (Coin Change)
IDE Q&A GeeksQuiz
Dynamic Programming | Set 7 (Coin Change)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[],
m1, n) and count(S[], m, nSm).
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...m1] coins to get sum nint count( int S[], int m, int n ) // If n is 0 then there is 1 solution (do not include any coin) if (n == 0) return 1; // If n is less than 0 then no solution exists if (n < 0) return 0; // If there are no coins and n is greater than 0, then no solution exist if (m <=0 && n >= 1) return 0; // count is sum of solutions (i) including S[m1] (ii) excluding S[m1] return count( S, m 1, n ) + count( S, m, nS[m1] );
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.
C() --> count() C(1,2,3, 5) / \ / \ C(1,2,3, 2) C(1,2, 5) / \ / \ / \ / \C(1,2,3, -1) C(1,2, 2) C(1,2, 3) C(1, 5) / \ / \ / \ / \ / \ / \ C(1,2,0) C(1,2) C(1,2,1) C(1,3) C(1, 4) C(, 5) / \ / \ / \ / \ / \ / \ / \ / \ . . . . . . C(1, 3) C(, 4) / \ / \ . .
Since same suproblems are called again, this problem has Overlapping Subprolems property. So the Coin
Change problem has both properties (see this and 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 table[][] in bottom up manner.
Dynamic Programming Solution
Run on IDE
// Driver program to test above functionint main() int i, j; int arr[] = 1, 2, 3; int m = sizeof(arr)/sizeof(arr[0]); printf("%d ", count(arr, m, 4)); getchar(); return 0;
#include<stdio.h> int count( int S[], int m, int n ) int i, j, x, y; // We need n+1 rows as the table is consturcted in bottom up manner using // the base case 0 value case (n = 0) int table[n+1][m]; // Fill the enteries for 0 value case (n = 0)
Time Complexity: O(mn)
Following is a simplified version of method 2. The auxiliary space required here is O(n) only.
Run on IDE
// Fill the enteries for 0 value case (n = 0) for (i=0; i<m; i++) table[0][i] = 1; // Fill rest of the table enteries in bottom up manner for (i = 1; i < n+1; i++) for (j = 0; j < m; j++) // Count of solutions including S[j] x = (iS[j] >= 0)? table[i S[j]][j]: 0; // Count of solutions excluding S[j] y = (j >= 1)? table[i][j1]: 0; // total count table[i][j] = x + y; return table[n][m1]; // Driver program to test above functionint main() int arr[] = 1, 2, 3; int m = sizeof(arr)/sizeof(arr[0]); int n = 4; printf(" %d ", count(arr, m, n)); return 0;
Run on IDE
int count( int S[], int m, int n ) // table[i] will be storing the number of solutions for // value i. We need n+1 rows as the table is consturcted // in bottom up manner using the base case (n = 0) int table[n+1]; // Initialize all table values as 0 memset(table, 0, sizeof(table)); // Base case (If given value is 0) table[0] = 1; // 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[jS[i]]; return table[n];
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
163 Comments Category: Misc Tags: Dynamic Programming
Related Posts:
GIT – Let’s Get Into It
How to learn any technology inside out?
Bitmasking and Dynamic Programming | Set 1 (Count ways to assign unique cap to every person)
SAP Labs Interview Experience | Set 11 (OnCampus)
Mistakes To Avoid While Building An ECommerce App
Wooqer Interview Experience | Set 1 (onCampus)
Factset Interview Experience | Set 3 (OnCampus)
Find all possible outcomes of a given expression
49Like Tweet 3 15
Writing code in comment? Please use code.geeksforgeeks.org, generate link and share the link here.
163 Comments GeeksforGeeks Login1
Share⤤ Sort by Newest
Join the discussion…
Recommend 6
• Reply •
Tushar Dwivedi • 15 days ago
I solved this problem with all the three ways. ie. Recursion, DPmemoization, and DPtabulation.
C++ implementation : https://ideone.com/14bBIv.Below were the results :(Input taken via stdin)
For n = 10recursion : 0 seconds and 14 microsecondsmemoization : 0 seconds and 17 microsecondstabulation : 0 seconds and 17 microseconds
For n =100recursion : 0 seconds and 1300 microsecondsmemoization : 0 seconds and 1270 microsecondstabulation : 0 seconds and 35 microseconds
What I am unable to understand , is that why for slightly larger input, memoization istaking almost same amount of time as simple recursive solution ? Shouldn'tmemoization take even lesser time than tabulation in this case, as it skips many uselesscalculations from the matrix, that have to be done in case of tabulation ? Or is it due torecursive calls ?
• Reply •
Arpit Quickgun Arora • 18 days ago
explanation for bottomup method just convert the logic count(S, n, m) = count(S, n Sm, m) + count(S, n, m1) to tableform table[n][m] = table[n][m1] + table[n s[m]][m].since we have already initialised the values for n = 0 and m = 0(if (n % s[0] == 0) thentable[n][0] = 1), we can run loop from n = 1onwards and fill the table.Also, if n < 0, return 0;Now while filling the table, we can notice that to find any cell value, we just values fromthe previous row and from the same row for lesser values of n(which have already beenfilled). Using this, the space optimised version can be derived.
• Reply •
dividebyzero • 22 days ago
In the last case, shouldn't it be `for(int j=S[i]; j<=n; j+=S[i])`?
Mandeep 17 days ago> dividebyzero
Share ›
Share ›
Share ›
• Reply •
Mandeep • 17 days ago> dividebyzero
Even I had the same doubt, but later I figured this out.Suppose u have coins 1,3 with n = 5.Suppose that you have already processed the j loop for coin 1, that leave youwith table as 1,1,1,1,1,1 since all values from 0 to 5 can be done in only 1way(i.e. using all 1's).Now think that you are processing the j loop for S[i] = 3.That means you have a new way to make value 3 (111, 3).so u update table[3] to 2. But according to your logic, it should try to update thenext value of table[6] (since according to you, j += S[i]). But think about the caseof 4. Don't you have a new way to make change for 4?? one was 1111, now thenew one is 1,3.Because of this reason, you do j++ and NOT j+=S[i].
• Reply •
Gokul NC • 23 days ago
How do you find the least number of coins required that can make any desired amount??
• Reply •
ddddd • 24 days ago
2nd dp approach is wrong ,duplicates are counted as well
• Reply •
ddddd • 24 days ago> ddddd
if your order of coins in the solution mattered,then second approach is right
• Reply •
Anthony • a month ago
I did not understand the DP logic . I struggled for hours . Can anyone help me out onhow the algorithm works ?
Abhishek Tiwari • a month ago
I have a query.Would this method not work...??Suppose we have to find the sum x.And coins allowed are contained in array A.
Thenfor i in A:Count(x)+= (Count(xi));
?
Share ›
Share ›
Share ›
Share ›
Share ›
• Reply •
If not then what's the problem( instead of memory overflow,which can always beeliminated using DP table.)
• Reply •
Aadil Ahmad • a month ago
what if order matters. like 1,1,2 is different from 2,1,1.
• Reply •
Vivek • a month ago
Top Down Approachhttp://ideone.com/fHO2Ab
• Reply •
Manohar Tn • a month ago
I did code in the other way, I considered ways[m][n] where m is the number of coinsand n is the value to make.
Here is the code and let me know if there's any case i'm missing out or if there's anyerror.
http://ideone.com/hzzxze
• Reply •
Rajan Parmar • 2 months ago
why first row of table is filled with '1' ?
• Reply •
Marquis • 2 months ago> Rajan Parmar
This is to cover your base cases. Its easiest to see how this comes into play ifyou write out the table by hand following all of the variables as if you were thecompiler.
• Reply •
roshanl • 2 months ago
solution (2) is wrong. It will count duplicate combinations as well ( for denominations1,2,3 and target count 4, it will count 1+1+2 and 1+2+1)
• Reply •
Saurabh Kumar • 13 days ago> roshanl
1,1,1,1 , 2,2 , 3,1, 1,1,2 ans the solution is right
Goku • 2 months ago
@geeksforgeeks
Share ›
Share ›
Share ›
Share ›
Share ›
Share ›
Share ›
Share ›
• Reply •
@geeksforgeeks This is the varient for coin change problem.In this we have to find the minimum numberof coins required to get the given sum from the set of coin values given.Please publish it:)http://ideone.com/B7Ej9H
• Reply •
abhi • a month ago> Goku
Your variant is wrong on some test cases,say coin array is 1,2,3,4,5 and u have to make 15the o/p should be 5,but your program's o/p is 3
• Reply •
Goku • a month ago> abhi
bro answer would be 3 only.We have to find the minimum no. ofcoins.Using 3 coins each of value 5,we can get the sum as 15.
• Reply •
NIKHIL SINGH • 2 months ago
simple bottom up approachhttp://ideone.com/raTq4l
• Reply •
Ajcoo • 2 months ago
Guys I am not sure if this solution uses DP . Please take a look and comment..
http://ideone.com/GpI1Vg
• Reply •
Swapnil Jain • a month ago> Ajcoo
Yo yo yo amigo, that's dp...
Utkarsh • 2 months ago
WHY IT DOESN'T WORK FOR 1st example but for second#include<stdio.h>
int count(int dp[5],int s[3],int,int);
int main()
int s[3] = 1,2,3;
Share ›
Share ›
Share ›
Share ›
Share ›
Share ›
• Reply •
see more
int s[3] = 1,2,3;
int dp[5]=0;
int m = 2; // m is the index of last element in set s
int n = 4;
printf(" %d ", count(dp,s,m,n));
return 0;
• Reply •
Utkarsh • 2 months ago> Utkarsh
printf("n=%d m= %d dp[n]= %d\n",n,m,dp[n]); was for debugging purpose,, nomeaning to solution
• Reply •
Carmelina Contarino • 2 months ago
How would we print all the combinations of the coins used for change?
Not just the # ways...
• Reply •
Goku • 2 months ago> Carmelina Contarino
backtracking
• Reply •
Srinivas Pittala • 2 months ago> Goku
tracing back
• Reply •
Carmelina Contarino • 2 months ago> Srinivas Pittala
I guess no backtracking and neither tracingback :(
• Reply •
Arnab • 3 months ago
I think the simplified version of method two considers the sequence also. i.e (3,3,5) and(3,5,3) to sequence are considered different.
1
Raj • 2 months ago> Arnab
Just do this.
Share ›
Share ›
Share ›
Share ›
Share ›
Share ›
Share ›
• Reply •
table[j] += jS[i] >= 0 ? table[jS[i]] : 0;
• Reply •
Abhishek Jaisingh • 3 months ago> Arnab
absolutely!
• Reply •
Abhi • 3 months ago
can anyone explain the logic of the simplified version of method 2??
• Reply •
Sathiyaseelan • 2 months ago> Abhi
Consider the following,The simplified approach2 is arrived with the below approach,
Consider the rows as coins, and columns are from 1..Nso the loop will become,So at each outer iteration(for each coin), we just need the previous row, insteadof the entire 2d array (ith row depends on i1th row only)
Which leads to the simplified approach of 2.
With single row, before each iteration, the single_row contains values ofprevious iteration, in which we can add the values.At end of each iteration, the single_row contains the current row values withprevious row values.
for(int i=0;i<m;i++) for(int="" j="0;j<=n;j++)" didn't="" mention="" the="" base=""cases="" dp[i][j]="" +="dp[i1][j]" hope="" it="" helps="">
2
• Reply •
Vishlesh • 2 months ago> Abhi
Abhi did u got any reply or understood logic behind method 2?
• Reply •
Abhi • 2 months ago> Vishlesh
didnt got any reply..please explain ..and thanx for the concern bro
• Reply •
Shitiz • 3 months ago
If I run the last method on arr[]=2,3 and sum=4, answer should be 2 but it is giving 1. Idon't know why? Please check
Share ›
Share ›
Share ›
Share ›
Share ›
Share ›
Share ›
• Reply •
Shitiz • 3 months ago> Shitiz
Sorry I misread the problem
• Reply •
abhi • 3 months ago
what is the time complexity of method 1?
• Reply •
HuntXT • 2 months ago> abhi
It would be exponential, 2^(n), although deriving the exact would be bit lengthyand difficult.
Since at each moment we have two choices , it would be a binary tree, now,at each height of binary tree we are doing some constant work, so, timecomplexity at each level => no. of elements at that level * C [ some constant]This we are doing for the complete tree, hence total no, of element are:1 + 2^1 + 2^2 + 2^3 + ...... 2^k , where k is height of tree....=> 2^(k+1)1;
Now, to find k, we can approx that k may be (m1 + N/s[0]),as we are not doing anything till the m1 then at the smallest denomination weare making the change.
• Reply •
akash dwivedi • 3 months ago
can anyone please tell the mistake error was showing of segmentation fault
https://ideone.com/l2sAwM
• Reply •
Return_0 • 3 months ago> akash dwivedi
arr[size1] should be there instead of arr[size]..
• Reply •
akash dwivedi • 3 months ago> Return_0
thanks
wa • 5 months ago
private static int minNumberOfCoinsSumRecur(int v[], int n) Arrays.fill(t, Integer.MAX_VALUE);if (n < 0)
Share ›
Share ›
Share ›
Share ›
Share ›
Share ›
• Reply •
if (n < 0)return Integer.MAX_VALUE;if (n == 0)return 0;if (t[n] != Integer.MAX_VALUE)return t[n];int ans = Integer.MAX_VALUE;t[0] = 0;for (int i = 0; i < v.length; i++) for (int j = v[i]; j <= n; j++) t[j] = Math.min(1 + t[j v[i]], t[j]);return t[n];
private static int minNumberOfCoinsSum(int[] arr, int sum) Arrays.fill(t, Integer.MAX_VALUE);t[0] = 0;for (int i = 0; i < arr.length; i++) for (int j = arr[i]; j <= sum; j++)t[j] = Math.min(t[j], 1 + t[j arr[i]]);return t[sum];
• Reply •
Neha • 5 months ago
How to print the combinations in iterative DP Solution Method 1 ?
• Reply •
Saurabh • 6 months ago
http://ideone.com/cA9ShC
This is a simple code without sub structures.
• Reply •
Techie Me • 6 months ago
Wonderful explanation.. Really appreciate your effort... Here is a Java version of theapplication and a much deeper dive into the approach.
http://techieme.in/minimumnum...
Mission Peace • 7 months ago
Share ›
Share ›
Share ›
Share ›
Load more comments
• Reply •
https://www.youtube.com/watch?...
1
• Reply •
VivekH • 2 months ago> Mission Peace
Please read the questions properly. It ask how many different ways you canhave so that sum is equal to a given value. Where as this video calculates theminimum number of coins to get to the given Sum
• Reply •
Mission Peace • 7 months ago
https://www.youtube.com/watch?...
1
• Reply •
Abhi • 7 months ago
GeeksforGeeks we can use this simple method
int count(int arr[],int s,int m) //s is the number of coin in array;//m is the number which we want to get //from the given coins
int dp[m+1];
dp[0]=0;
int i;
int j;
for(i=1;i<=m;i++)
dp[i]=0;
for(j=0;j<s;j++) ="" if(i="">=arr[j] && dp[i]<dp[iarr[j]]+1) ="" dp[i]="dp[iarr[j]]+1;" =""="" ="" return="" dp[m];="" ="">
Share ›
Share ›
Share ›
Share ›
@geeksforgeeks, Some rights reserved Contact Us! About Us! Advertise with us!