Coin Change Problem in C++
Last Updated :
07 Aug, 2024
In this article, we will learn how to count all combinations of coins to make a given value sum using the C++ programming language. The Coin Change Problem involves finding the number of ways to make change for a given amount using a set of coin denominations.
Example:
Consider an integer array coins[] representing different coin denominations and an integer amount, determine the number of combinations of coins that sum up to the given amount.
Input:
coins = [1, 2, 5]
amount = 5
Output:
4
Explanation:
The different combinations are:
1) 1 + 1 + 1 + 1 + 1
2) 1 + 1 + 1 + 2
3) 1 + 2 + 2
4) 5
How to Solve Coin Change Problem in C++?
1. Count All Combinations Using Recursion
In the recursive approach, we will generate all possible combinations and count those that sum to the given amount using recursion.
Recurrence Relation:
count(coins,n,sum) = count(coins,n,sum-count[n-1]) + count(coins,n-1,sum)
Coin Change Using RecursionApproach:
- Base Condition:
- If the amount is 0, there is one way to make change (using no coins), so return 1.
- If the amount is negative or there are no coins left, return 0 as no valid combination can be formed.
- For each coin, recursively count the combinations by
- including the coin (reduce the amount by the coin's value) and
- excluding the coin (move to the next coin).
Below is the implementation of the above approach:
C++
// C++ program to solve coin change problem using recursion
#include <iostream>
#include <vector>
using namespace std;
// Returns the count of ways we can
// sum coins[0...n-1] coins to get sum "sum"
int count(int coins[], int n, int sum)
{
// If sum is 0 then there is 1 solution
// (do not include any coin)
if (sum == 0)
return 1;
// If sum is less than 0 then no
// solution exists
if (sum < 0)
return 0;
// If there are no coins and sum
// is greater than 0, then no
// solution exist
if (n <= 0)
return 0;
// count is sum of solutions (i)
// including coins[n-1] (ii) excluding coins[n-1]
return count(coins, n, sum - coins[n - 1]) + count(coins, n - 1, sum);
}
int main()
{
int i, j;
int coins[] = {1, 2, 3};
int n = sizeof(coins) / sizeof(coins[0]);
int sum = 5;
cout << " " << count(coins, n, sum);
return 0;
}
Time Complexity: O(2sum)
Auxiliary Space: O(sum)
2. Count All Combinations Using Dynamic Programming (Memoization)
We can further optimize the recursive solution by storing the results of previously solved subproblems in a 2D array to avoid redundant calculations.
Approach:
- Initialize Memoization Table by creating a 2D array dp of size (n+1) x (amount+1) and initialize all values to -1.
- For each subproblem:
- if the result is already computed, return it from the table.
- Otherwise, compute the result recursively, store it in the memoization table, and return the stored value.
Below is the implementation of the above approach:
C++
// C++ program to solve coin change problem using Dynamic Programming (Memoization
#include <iostream>
#include <vector>
using namespace std;
// Recursive function to count the numeber of distinct ways
// to make the sum by using n coins
int count(vector<int> &coins, int n, int sum, vector<vector<int>> &dp)
{
// Base Case
if (sum == 0)
return dp[n][sum] = 1;
// If number of coins is 0 or sum is less than 0 then
// there is no way to make the sum.
if (n == 0 || sum < 0)
return 0;
// If the subproblem is previously calculated then
// simply return the result
if (dp[n][sum] != -1)
return dp[n][sum];
// Two options for the current coin
return dp[n][sum] = count(coins, n, sum - coins[n - 1], dp) + count(coins, n - 1, sum, dp);
}
int32_t main()
{
int tc = 1;
// cin >> tc;
while (tc--)
{
int n, sum;
n = 3, sum = 5;
vector<int> coins = {1, 2, 3};
// 2d dp array to store previously calculated
// results
vector<vector<int>> dp(n + 1, vector<int>(sum + 1, -1));
int res = count(coins, n, sum, dp);
cout << res << endl;
}
}
Time Complexity: O(N*sum), where N is the number of coins and sum is the target sum.
Auxiliary Space: O(N*sum)
3. Count All Combinations Using Dynamic Programming (Tabulation)
We can use the bottom-up approach by building the solution iteratively using a table to store intermediate results.
Approach:
- Create a 2D dp array with rows and columns equal to the number of coin denominations and target sum.
- dp[0][0] will be set to 1 which represents the base case where the target sum is 0, and there is only one way to make the change by not selecting any coin.
- Iterate through the rows of the dp array (i from 1 to n), representing the current coin being considered.
- The inner loop iterates over the target sums (j from 0 to sum).
- Add the number of ways to make change without using the current coin, i.e., dp[i][j] += dp[i-1][j].
- Add the number of ways to make change using the current coin, i.e., dp[i][j] += dp[i][j-coins[i-1]].
- dp[n][sum] will contain the total number of ways to make change for the given target sum using the available coin denominations.
Below is the implementation of above approach:
C++
// C++ program to solve coin change problem using Dynamic Programming (Tabulation)
#include <iostream>
#include <vector>
using namespace std;
// Returns total distinct ways to make sum using n coins of
// different denominations
int count(vector<int> &coins, int n, int sum)
{
// 2d dp array where n is the number of coin
// denominations and sum is the target sum
vector<vector<int>> dp(n + 1, vector<int>(sum + 1, 0));
// Represents the base case where the target sum is 0,
// and there is only one way to make change: by not
// selecting any coin
dp[0][0] = 1;
for (int i = 1; i <= n; i++)
{
for (int j = 0; j <= sum; j++)
{
// Add the number of ways to make change without
// using the current coin,
dp[i][j] += dp[i - 1][j];
if ((j - coins[i - 1]) >= 0)
{
// Add the number of ways to make change
// using the current coin
dp[i][j] += dp[i][j - coins[i - 1]];
}
}
}
return dp[n][sum];
}
// Driver Code
int main()
{
vector<int> coins{1, 2, 3};
int n = 3;
int sum = 5;
cout << count(coins, n, sum);
return 0;
}
Time complexity : O(N*sum)
Auxiliary Space : O(N*sum)
4. Count All Combinations Using Dynamic Programming (Space Optimized)
In the above tabulation approach we are only using dp[i-1][j] and dp[i][j] , so we can further optimize the space complexity of the tabulation method by using only a 1D array.
Approach:
- Create a 1D dp array, dp[i] represents the number of ways to make the sum i using the given coin denominations.
- The outer loop iterates over the coins, and the inner loop iterates over the target sums. For each dp[j], it calculates the number of ways to make change using the current coin denomination and the previous results stored in dp.
- dp[sum] contains the total number of ways to make change for the given target sum using the available coin denominations. This approach optimizes space by using a 1D array instead of a 2D DP table.
Below is the implementation of the above approach:
C++
// C++ program to solve coin change problem using Dynamic Programming (Space Optimized)
#include <cstring> // Include the cstring header for memset
#include <iostream>
#include <vector>
using namespace std;
int count(const vector<int> &coins, int n, int sum)
{
// dp[i] will be storing the number of solutions for value i.
// We need sum+1 rows as the dp is constructed in bottom up manner using the base case (sum = 0)
vector<int> dp(sum + 1, 0);
// Base case (If given value is 0)
dp[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 < n; i++)
{
for (int j = coins[i]; j <= sum; j++)
{
dp[j] += dp[j - coins[i]];
}
}
return dp[sum];
}
int main()
{
vector<int> coins = {1, 2, 3};
int n = coins.size();
int sum = 5;
cout << count(coins, n, sum) << endl;
return 0;
}
Time complexity : O(N*sum)
Auxiliary Space : O(sum)
Similar Reads
Number System Conversion in C
Number system conversion is a fundamental concept in computer science and programming. It involves changing the representation of a number from one base to another, such as converting a decimal number to binary or a hexadecimal number to binary. In this article, we will create a console program in t
8 min read
How to Read and Print an Integer value in C++
The given task is to take an integer as input from the user and print that integer in C++ language. In this article, we will learn how to read and print an integer value. In the below program, the syntax and procedures to take the integer as input from the user is shown in C++ language. Standard Inp
2 min read
Decision Making in C++
Decision-making is the process to make a decision about which part of the code should be executed or not based on some condition. Decision-making in C++ involves the usage of conditional statements (also called decision control statements) to execute specific blocks of code primarily based on given
8 min read
VS Code | Compile and Run in C++
In this article, we will learn how to compile and run C++ program in VS Code. There are two ways of doing that you can use any one of them as per your convenience. It is to be noted that a majority of competitive programmers use C++, therefore the compilation and execution of the program needs to be
3 min read
C++ Programming Language
C++ is a computer programming language developed by Bjarne Stroustrup as an extension of the C language. It is known for is fast speed, low level memory management and is often taught as first programming language. It provides: Hands-on application of different programming concepts.Similar syntax to
5 min read
std::count() in C++ STL
In C++, the count() is a built-in function used to find the number of occurrences of an element in the given range. This range can be any STL container or an array. In this article, we will learn about the count() function in C++. Letâs take a quick look at a simple example that uses count() method:
3 min read
rand() and srand() in C++
The std::rand() in C++ is a built-in function that is used to generate a series of random numbers. It will generate random numbers in the range [0, RAND_MAX) where RAND_MAX is a constant whose default value may vary but is granted to be at least 32767. It is defined inside <cstdlib> and <st
3 min read
C++ if else if Ladder
In C++, the if-else-if ladder helps the user decide from among multiple options. The C++ if statements are executed from the top down. As soon as one of the conditions controlling the if is true, the statement associated with that if is executed, and the rest of the C++ else-if ladder is bypassed. I
3 min read
Basic Input / Output in C++
In C++, input and output are performed in the form of a sequence of bytes or more commonly known as streams. Input Stream: If the direction of flow of bytes is from the device (for example, Keyboard) to the main memory then this process is called input.Output Stream: If the direction of flow of byte
5 min read
accumulate() and partial_sum() in C++ STL
accumulate() and partial_sum() functions are used to find the sum or any other accumulated value that is obtained by doing the addition or any other binary operation on the elements in the given range. Both of these functions are the part of STL Numeric Library and defined inside <numeric> hea
4 min read