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.
# Dynamic Programming Python implementation of Coin # Change problem def count(S, m, n):
# We need n+1 rows as the table is constructed
# in bottom up manner using the base case 0 value
# case (n = 0)
table = [[ 0 for x in range (m)] for x in range (n + 1 )]
# Fill the entries for 0 value case (n = 0)
for i in range (m):
table[ 0 ][i] = 1
# Fill rest of the table entries in bottom up manner
for i in range ( 1 , n + 1 ):
for j in range (m):
# Count of solutions including S[j]
x = table[i - S[j]][j] if i - S[j] > = 0 else 0
# Count of solutions excluding S[j]
y = table[i][j - 1 ] if j > = 1 else 0
# total count
table[i][j] = x + y
return table[n][m - 1 ]
# Driver program to test above function arr = [ 1 , 2 , 3 ]
m = len (arr)
n = 4
print (count(arr, m, n))
# This code is contributed by Bhavya Jain |
4
Time complexity: O(mn) where m is the number of coin denominations and n is the target amount.
Auxiliary space complexity: O(mn) as a 2D table of size mxn is created to store the number of ways to make the target amount using the coin denominations.
# Dynamic Programming Python implementation of Coin # Change problem def count(S, m, n):
# table[i] will be storing the number of solutions for
# value i. We need n+1 rows as the table is constructed
# in bottom up manner using the base case (n = 0)
# Initialize all table values as 0
table = [ 0 for k in range (n + 1 )]
# 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 i in range ( 0 ,m):
for j in range (S[i],n + 1 ):
table[j] + = table[j - S[i]]
return table[n]
# Driver program to test above function arr = [ 1 , 2 , 3 ]
m = len (arr)
n = 4
x = count(arr, m, n)
print (x)
# This code is contributed by Afzal Ansari |
4
Complexity Analysis:
For both solutions the time and space complexity is the same:
Time Complexity: O(n*m)
Auxiliary Space: O(n)
Though the first solution might be a little slow as it has multiple loops.
Approach: Recursion + Memoization.
In this approach, we first define a memo dictionary to store the results of previously computed subproblems.
- We then define a helper function that takes in the current amount and the current coin index.
- The function helper is a recursive function that checks all the possible combinations of coins to reach the target sum.
- Then we print the possible ways to make the target sum using the given set of coins.
def count_coins(coins, target):
memo = {}
def helper(amount, idx):
# Check if the solution for this subproblem already exists
if (amount, idx) in memo:
return memo[(amount, idx)]
# Base case: If the target sum is reached
if amount = = 0 :
return 1
# Base case: If the target sum cannot be reached using remaining coins
if amount < 0 or idx > = len (coins):
return 0
# Recursively calculate the number of possible ways using the current coin or skipping it
memo[(amount, idx)] = helper(amount - coins[idx], idx) + helper(amount, idx + 1 )
return memo[(amount, idx)]
# Call the recursive function with the initial parameters
return helper(target, 0 )
# Test the function arr = [ 1 , 2 , 3 ]
n = 4
x = count_coins(arr, n)
print (x)
|
4
Time Complexity: O(mn), where ‘m’ is the number of coins and ‘n’ is the target sum.
Auxiliary Space: O(n), as we are using a table of size (n+1) to store the subproblem solutions.
Please refer complete article on Dynamic Programming | Set 7 (Coin Change) for more details!