dynamic programming (coin change)

13
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 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) return // If n is less than 0 then no solution exists if (n < 0) return // If there are no coins and n is greater than 0, then no solution exist if (m <=0 && n >= 1) return // count is sum of solutions (i) including S[m1] (ii) excluding S[m1] return count( S, m 1, n ) + count( S, m, nS[m1] ); }

Upload: vineet-kumar

Post on 07-Dec-2015

227 views

Category:

Documents


2 download

DESCRIPTION

Coin Change Problem: DP Solution

TRANSCRIPT

Page 1: 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[],

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 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[m­1] (ii) excluding S[m­1] return count( S, m ­ 1, n ) + count( S, m, n­S[m­1] );

Page 2: Dynamic Programming (Coin Change)

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)

Page 3: Dynamic Programming (Coin Change)

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 = (i­S[j] >= 0)? table[i ­ S[j]][j]: 0; // Count of solutions excluding S[j] y = (j >= 1)? table[i][j­1]: 0; // total count table[i][j] = x + y; return table[n][m­1]; // 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[j­S[i]]; return table[n];

Page 4: Dynamic Programming (Coin Change)

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 (On­Campus)

Mistakes To Avoid While Building An E­Commerce App

Wooqer Interview Experience | Set 1 (on­Campus)

Factset Interview Experience | Set 3 (On­Campus)

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

Page 5: Dynamic Programming (Coin Change)

• Reply •

Tushar Dwivedi • 15 days ago

I solved this problem with all the three ways. ie. Recursion, DP­memoization, and DP­tabulation.

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 bottom­up method ­just convert the logic count(S, n, m) = count(S, n ­ Sm, m) + count(S, n, m­1) to tableform ­table[n][m] = table[n][m­1] + 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 ›

Page 6: Dynamic Programming (Coin Change)

• 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(x­i));

?

Share ›

Share ›

Share ›

Share ›

Share ›

Page 7: Dynamic Programming (Coin Change)

• 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 ›

Page 8: Dynamic Programming (Coin Change)

• 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 ›

Page 9: Dynamic Programming (Coin Change)

• 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 ›

Page 10: Dynamic Programming (Coin Change)

• Reply •

table[j] += j­S[i] >= 0 ? table[j­S[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 i­1th 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&lt;=n;j++)" didn't="" mention="" the="" base=""cases="" dp[i][j]="" +="dp[i­1][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 ›

Page 11: Dynamic Programming (Coin Change)

• 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 (m­1 + N/s[0]),as we are not doing anything till the m­1 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[size­1] 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 ›

Page 12: Dynamic Programming (Coin Change)

• 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/minimum­num...

Mission Peace • 7 months ago

Share ›

Share ›

Share ›

Share ›

Page 13: Dynamic Programming (Coin Change)

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[i­arr[j]]+1) ="" dp[i]="dp[i­arr[j]]+1;" =""="" ="" return="" dp[m];="" ="">

Share ›

Share ›

Share ›

Share ›

@geeksforgeeks, Some rights reserved Contact Us! About Us! Advertise with us!