Skip to content
Related Articles

Related Articles

Improve Article

Coin Change | DP-7

  • Difficulty Level : Hard
  • Last Updated : 22 Jul, 2021
 

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 the total number of solutions, we can divide all set solutions into 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.

C++




// Recursive C++ program for
// coin change problem.
#include <bits/stdc++.h>
using namespace std;
 
// 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)
        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]);
}
 
// Driver code
int main()
{
    int i, j;
    int arr[] = { 1, 2, 3 };
    int m = sizeof(arr) / sizeof(arr[0]);
     
    cout << " " << count(arr, m, 4);
     
    return 0;
}
 
// This code is contributed by shivanisinghss2110


C




// Recursive C program for
// coin change problem.
#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)
        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] );
}
 
// Driver program to test above function
int 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;
}


Python3




# Recursive Python3 program for
# coin change problem.
 
# Returns the count of ways we can sum
# S[0...m-1] coins to get sum n
def count(S, m, 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 and 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] );
 
# Driver program to test above function
arr = [1, 2, 3]
m = len(arr)
print(count(arr, m, 4))
 
# This code is contributed by Smitha Dinesh Semwal


C#




// Recursive C# program for
// coin change problem.
using System;
 
class GFG
{
    // Returns the count of ways we can
    // sum S[0...m-1] coins to get sum n
    static 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 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] );
    }
     
    // Driver program
    public static void Main()
    {
         
        int []arr = {1, 2, 3};
        int m = arr.Length;
        Console.Write( count(arr, m, 4));
         
         
    }
}
// This code is contributed by Sam007


PHP




<?php
// Recursive PHP program for
// coin change problem.
 
// Returns the count of ways we can
// sum S[0...m-1] coins to get sum n
function coun($S, $m, $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 coun($S, $m - 1,$n ) +
           coun($S, $m, $n - $S[$m - 1] );
}
 
    // Driver Code
    $arr = array(1, 2, 3);
    $m = count($arr);
    echo coun($arr, $m, 4);
     
// This code is contributed by Sam007
?>


Javascript




<script>
// Recursive javascript program for
// coin change problem.
    
// Returns the count of ways we can
// sum S[0...m-1] coins to get sum n
function count(S , m , 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] );
}
 
// Driver program to test above function
var arr = [1, 2, 3];
var m = arr.length;
document.write( count(arr, m, 4));
 
// This code is contributed by Amit Katiyar
</script>


Output

 4

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 subproblems are called again, this problem has Overlapping Subproblems 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  

C++




// C++ program for coin change problem.
#include<bits/stdc++.h>
 
using namespace std;
 
int count( int S[], int m, int n )
{
    int i, j, x, y;
 
    // We need n+1 rows as the table
    // is constructed 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)
    for (i = 0; i < m; i++)
        table[0][i] = 1;
 
    // Fill rest of the table entries
    // 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 Code
int main()
{
    int arr[] = {1, 2, 3};
    int m = sizeof(arr)/sizeof(arr[0]);
    int n = 4;
    cout << count(arr, m, n);
    return 0;
}
 
// This code is contributed
// by Akanksha Rai(Abby_akku)


C




// C program for coin change problem.
#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 constructed
    // 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)
    for (i=0; i<m; i++)
        table[0][i] = 1;
 
    // Fill rest of the table entries 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 function
int main()
{
    int arr[] = {1, 2, 3};
    int m = sizeof(arr)/sizeof(arr[0]);
    int n = 4;
    printf(" %d ", count(arr, m, n));
    return 0;
}


Java




/* Dynamic Programming Java implementation of Coin
   Change problem */
import java.util.Arrays;
 
class CoinChange
{
    static long countWays(int S[], int m, int n)
    {
        //Time complexity of this function: O(mn)
        //Space Complexity of this function: O(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)
        long[] table = new long[n+1];
 
        // Initialize all table values as 0
        Arrays.fill(table, 0);   //O(n)
 
        // 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];
    }
 
    // Driver Function to test above function
    public static void main(String args[])
    {
        int arr[] = {1, 2, 3};
        int m = arr.length;
        int n = 4;
        System.out.println(countWays(arr, m, n));
    }
}
// This code is contributed by Pankaj Kumar


Python




# 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


C#




/* Dynamic Programming C# implementation of Coin
Change problem */
using System;
 
class GFG
{
    static long countWays(int []S, int m, int n)
    {
        //Time complexity of this function: O(mn)
        //Space Complexity of this function: O(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)
        int[] table = new int[n+1];
 
        // Initialize all table values as 0
        for(int i = 0; i < table.Length; i++)
        {
            table[i] = 0;
        }
 
        // 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];
    }
 
    // Driver Function
    public static void Main()
    {
        int []arr = {1, 2, 3};
        int m = arr.Length;
        int n = 4;
        Console.Write(countWays(arr, m, n));
    }
}
// This code is contributed by Sam007


PHP




<?php
// PHP program for
// coin change problem.
 
function count1($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;
    for ($i = 0; $i < $n + 1; $i++)
    for ($j = 0; $j < $m; $j++)
        $table[$i][$j] = 0;
     
    // Fill the enteries for
    // 0 value case (n = 0)
    for ($i = 0; $i < $m; $i++)
        $table[0][$i] = 1;
 
    // Fill rest of the table
    // entries 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 Code
$arr = array(1, 2, 3);
$m = count($arr);
$n = 4;
echo count1($arr, $m, $n);
 
// This code is contributed by mits
?>


Javascript




<script>
 
/* Dynamic Programming javascript implementation of Coin
   Change problem */
 
function countWays(S , m , n)
{
    //Time complexity of this function: O(mn)
    //Space Complexity of this function: O(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
    //O(n)
    var table = Array(n+1).fill(0);
     
 
    // 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=0; i<m; i++)
        for (j=S[i]; j<=n; j++)
            table[j] += table[j-S[i]];
 
    return table[n];
}
 
// Driver Function to test above function
var arr = [1, 2, 3];
var m = arr.length;
var n = 4;
document.write(countWays(arr, m, n));
 
// This code is contributed by 29AjayKumar
 
</script>


Output

4

Time Complexity: O(mn) 
Following is a simplified version of method 2. The auxiliary space required here is O(n) only. 

C++




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 constructed         
 // 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];         
}         


Java




public static 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 constructed
    // in bottom up manner using the base case (n = 0)
    int table[]=new int[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(int i=0; i<m; i++)
        for(int j=S[i]; j<=n; j++)
            table[j] += table[j-S[i]];
 
    return table[n];
}


Python




# 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


C#




// Dynamic Programming C# implementation
// of Coin Change problem
using System;
 
class GFG
{
static 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 constructed in bottom up manner
    // using the base case (n = 0)
    int [] table = new int[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(int i = 0; i < m; i++)
        for(int j = S[i]; j <= n; j++)
            table[j] += table[j - S[i]];
 
    return table[n];
}
 
// Driver Code
public static void Main()
{
    int []arr = {1, 2, 3};
    int m = arr.Length;
    int n = 4;
    Console.Write(count(arr, m, n));
}
}
 
// This code is contributed by Raj


PHP




<?php
function count_1( &$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)
    $table = array_fill(0, $n + 1, NULl);
 
    // 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 = 0; $i < $m; $i++)
        for($j = $S[$i]; $j <= $n; $j++)
            $table[$j] += $table[$j - $S[$i]];
 
    return $table[$n];
}
 
// Driver Code
$arr = array(1, 2, 3);
$m = sizeof($arr);
$n = 4;
$x = count_1($arr, $m, $n);
echo $x;
 
// This code is contributed
// by ChitraNayal
?>


Javascript




<script>
    // Dynamic Programming Javascript implementation
    // of Coin Change problem
       
    function 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)
        let table = new Array(n + 1);
        table.fill(0);
 
        // 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(let i = 0; i < m; i++)
            for(let j = S[i]; j <= n; j++)
                table[j] += table[j - S[i]];
 
        return table[n];
    }
     
    let arr = [1, 2, 3];
    let m = arr.length;
    let n = 4;
    document.write(count(arr, m, n));
</script>


Output: 

4

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

Following is another Top Down DP Approach using memoization:

C++




#include <bits/stdc++.h>
using namespace std;
 
int coinchange(vector<int>& a, int v, int n,
               vector<vector<int> >& dp)
{
    if (v == 0)
        return dp[n][v] = 1;
    if (n == 0)
        return 0;
    if (dp[n][v] != -1)
        return dp[n][v];
    if (a[n - 1] <= v) {
        // Either Pick this coin or not
        return dp[n][v] = coinchange(a, v - a[n - 1], n, dp)
                          + coinchange(a, v, n - 1, dp);
    }
    else // We have no option but to leave this coin
        return dp[n][v] = coinchange(a, v, n - 1, dp);
}
int32_t main()
{
    int tc = 1;
    // cin >> tc;
    while (tc--) {
        int n, v;
        n = 3, v = 4;
        vector<int> a = { 1, 2, 3 };
        vector<vector<int> > dp(n + 1,
                                vector<int>(v + 1, -1));
        int res = coinchange(a, v, n, dp);
        cout << res << endl;
    }
}
// This Code is Contributed by
// Harshit Agrawal NITT


Output

4

Time Complexity: O(M*N)
Auxiliary Space: O(M*N)

Contributed by: Mayukh Sinha 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :