Articles by FavTutor
  • AI News
  • Data Structures
  • Web Developement
  • AI Code GeneratorNEW
  • Student Help
  • Main Website
No Result
View All Result
FavTutor
  • AI News
  • Data Structures
  • Web Developement
  • AI Code GeneratorNEW
  • Student Help
  • Main Website
No Result
View All Result
Articles by FavTutor
No Result
View All Result
Home Data Structures and Algorithms

Coin Change II Problem (C++, Java, Python)

Kartik Kukreja by Kartik Kukreja
April 7, 2025
Reading Time: 10 mins read
Coin Change II
Follow us on Google News   Subscribe to our newsletter

Money is the most essential thing that we deal with every day. Isn’t it interesting that we have so many denominations of money and can use them in different combinations to pay a certain amount? In this article, we will explore one very famous dynamic programming-based problem: Coin Change II. We will explore different solutions, from the brute force approach to the most optimal one.

Coin Change II Problem Statement

In the Coin Change II problem, we are given different denominations of money, like 1, 2, 5, 10, etc. We are given a total amount we need to form using combinations of these coins. We need to find the total number of possible combinations.

Let’s understand it better with an example:

Input:

coins: [ 1, 2, 3 ]
amount: 5

Output:

5

Explanation:

The 5 different possible combinations are:

5 = 3 + 2

5 = 3 + 1 + 1

5 = 2 + 2 + 1

5 = 2 + 1 + 1 + 1 

5 = 1 + 1 + 1 + 1 + 1

Example

Brute Force Approach: Using Recursion

The most basic solution is to find all the possible combinations and add the ones where the sum is equal to the amount. We can use recursion to explore all the possible combinations. The following steps need to be followed:

  • We will iterate over the coin array, and at each index, we have two options to either take that coin or ignore that coin.
  • Take a variable index, which we will use to iterate over the coins array, and initialize it to 0.
  • Write a recursive function such that, if we take the current coin, we will subtract its value from the total amount; else if we ignore it, the amount will remain the same.
  • The base case of the recursion will be if we have left with amount = 0, i.e., the combination is found, we can simply return 1 to add it to the answer, else if the coins array is traversed completely, return 0.
  • If we can take this coin, subtract the amount, and call for the remaining amount by passing the same index, we can infinitely take a coin.
  • If we skip this coin, increment the index and call the function again for the same amount.
  • Add the answer returned from both the recursion calls, and return it.

The time complexity for this solution will be O(2^(n*amount)) since we are exploring all the combinations using recursion.

Memoization Approach

We can improve the time complexity of the recursive solution by using the concept of memoization. We can make use of dynamic programming to store the results and reuse them for overlapping problems. If we have calculated the possible combinations of a certain amount, we do not need to calculate again whenever we get the same amount remaining.

Dynamic programming can be applied through these easy steps:

  • Write the same recursive function and use the below steps to apply memoization to it.
  • Create a 2d dp array of size n x ( amount + 1 ) to store the results of the sub-problems.
  • Initialize the dp array to -1; as for the combinations not possible the answer will be -1.
  • Before calculating again for a certain amount, we will first check it in our dp array ( dp[index][amount] ); if we have calculated it before, we can simply use it. 
  • Else, calculate the answer and set dp[index][amount] = answer, so that we can use it again for the sub-problems.

The time complexity for this solution will be O(n * amount), where n is the number of coins. There are at max n * amount number of possible combinations, so if we explore them all, the time complexity will be O(n*amount).

Tabulation Approach

The tabulation approach is nothing but a bottom-up version of the above memoization approach. Earlier we were starting from index 0 and amount. Now, we will begin with the amount as 0 and try to reach the solution.

The following steps are required to be followed in the solution:

  • Create a 2d dp array with size n x ( amount + 1 ).
  • If amount = 0, there is only one possible combination, so initialize dp[0][0] as 1.
  • Use a loop from 1 to n to iterate over the row of the dp array and find the solution for each index.
  • Use a nested loop to iterate over the amount, i.e., from 0 to amount.
  • If we take a current coin, add the dp[i][amount – coins[i-1]] since the value of that coin gets subtracted from the amount.
  • Otherwise, if we didn’t take that coin, we can simply add dp[i-1][amount].
  • Return the dp[n][amount], which contains the total number of possible combinations that can make the sum = amount

The time complexity for this solution will be O(n * amount), where n is the number of coins. We are using two nested loops, one from 1 to n and the other from 0 to amount. That’s why time complexity is O(n*amount).

Optimal Approach: Tabulation + Space Optimization

As we have seen in the above approaches, we have significantly reduced the time complexity, but space is still an issue for us. To reduce the space complexity, we need to optimize our tabulation solution.

We can observe that the answer for any sub-problem depends on two things, dp[i-1][amount] and dp[i][amount – coins[i] ], i.e., our answer depends on just the current and previous row. S,o instead of storing answers for each point, we can store just the current and previous rows. This will eventually bring the complexity down to O(2*amount).

The following modifications are needed to be done in the tabulation solution:

  • Use two arrays, i.e., current and previous of size = ( amount + 1 ), instead of a 2d dp array.
  • The current[amount – coins[i]] represents our dp[i][amount – coins[I] ], and the previous[amount] represents our dp[i-1][amount].
  • Initialize the current vector inside the loop 0 to amount so that we can calculate its values for each amount.
  • Update the previous = current once the calculations are performed, as the current row becomes the previous when we move to the next row.
  • Finally, return the answer as the previous[amount], which is nothing but equal to dp[n][amount].

Let’s take our example and understand the steps:

Input

Initialize the current and previous vectors:

current and previous vectors

Iteration: 1 Index = 1

Iteration: 1

Iteration: 2 Index = 2

Iteration: 2

The answer is previous[amount], i.e. 5

Answer

C++ Code

Here is the C++ Solution for the Coin Change II Problem:

#include <bits/stdc++.h>
using namespace std;

int main() {
    // Input
    vector<int> coins = {1, 2, 3};
    int amount = 5;
    int n = coins.size(); 

    // Initialize the previous vector
    vector<long> previous(amount + 1, 0);

    // Initialize base condition
    for (int i = 0; i <= amount; i++) {
        if (i % coins[0] == 0)
            previous[i] = 1;
    }

    for (int i = 1; i < n; i++) {
        // Initialize the current vector
        vector<long> current(amount + 1, 0);
        
        for (int targetAmount = 0; targetAmount <= amount; targetAmount++) {
            // If we ignore the current coin
            long ans1 = previous[targetAmount]; 
            
            // If we take the current coin
            long ans2 = 0;
            if (coins[i] <= targetAmount)
                ans2 = current[targetAmount - coins[i]];
        
            // Answer will be sum of both        
            current[targetAmount] = ans1 + ans2;
        }
        
        // Since current row now become previous
        previous = current;
    }

    cout << "Number of possible combinations are: " << previous[amount];
    return 0;
}

Java Code

Let’s implement it in Java:

import java.util.Arrays;

public class CoinChange {
    public static void main(String[] args) {
        // Input
        int[] coins = {1, 2, 3};
        int amount = 5;
        int n = coins.length;

        // Initialize the previous array
        long[] previous = new long[amount + 1];
        Arrays.fill(previous, 0);
        
        // Initialize base condition
        for (int i = 0; i <= amount; i++) {
            if (i % coins[0] == 0)
                previous[i] = 1;
        }

        // Loop through each coin
        for (int i = 1; i < n; i++) {
            // Initialize the current array
            long[] current = new long[amount + 1];
            Arrays.fill(current, 0);

            // Loop through each possible amount
            for (int targetAmount = 0; targetAmount <= amount; targetAmount++) {
                // If we ignore the current coin
                long ans1 = previous[targetAmount];
                
                // If we take the current coin
                long ans2 = 0;
                if (coins[i] <= targetAmount)
                    ans2 = current[targetAmount - coins[i]];
                
                // Answer will be sum of both
                current[targetAmount] = ans1 + ans2;
            }

            // Update previous array with current array
            previous = current;
        }

        System.out.println("Number of possible combinations are: " + previous[amount]);
    }
}

Python Code

Here is the Python code for the Coin Change II Problem:

def main():
    # Input
    coins = [1, 2, 3]
    amount = 5
    n = len(coins)

    # Initialize the previous array
    previous = [0] * (amount + 1)
    for i in range(amount + 1):
        if i % coins[0] == 0:
            previous[i] = 1

    # Loop through each coin
    for i in range(1, n):
        # Initialize the current array
        current = [0] * (amount + 1)

        # Loop through each possible amount
        for target_amount in range(amount + 1):
            # If we ignore the current coin
            ans1 = previous[target_amount]
            
            # If we take the current coin
            ans2 = 0
            if coins[i] <= target_amount:
                ans2 = current[target_amount - coins[i]]
            
            # Answer will be sum of both
            current[target_amount] = ans1 + ans2

        # Update previous array with current array
        previous = current

    print("Number of possible combinations are:", previous[amount])


if __name__ == "__main__":
    main()

Output:

Number of possible combinations are: 5

The time complexity for this solution will be O(n * amount), where n is the number of coins. We are using two nested loops, one from 1 to n and the other from 0 to amount. That’s why time complexity is O(n*amount).

The space complexity is O(amount), which is used by the previous and current arrays.

Conclusion

So, we explore one of the problems involving recursion and dynamic programming. We understood all the approaches to solve the problem of Coin Change II. We were able to reduce the time complexity from exponential to O(n*amount).

ShareTweetShareSendSend
Kartik Kukreja

Kartik Kukreja

I am a passionate computer science student with a knack for problem-solving and a passion for innovation. My interest in software development compelled me to undertake several projects in Web Development. I also have a huge interest in reading and writing technical blogs and have great experience in this domain. I'm excited to keep exploring the world of technology and making it more fun for everyone!

RelatedPosts

validate ip address

Validate IP Address Problem ( C++, JAVA, Python)

April 3, 2025
Shortest Palindrome Problem

Shortest Palindrome Problem ( C++, JAVA, Python)

April 4, 2025
Zigzag Conversion Problem

Zigzag Conversion Problem (C++, Java, Python)

April 4, 2025
Next Right Pointers In Each Node

Populating Next Right Pointers In Each Node (with code)

March 27, 2024
Minimum Size Subarray Sum

Minimum Size Subarray Sum Problem (C++, Java, Python)

April 7, 2025

About FavTutor

FavTutor is a trusted online tutoring service to connects students with expert tutors to provide guidance on Computer Science subjects like Java, Python, C, C++, SQL, Data Science, Statistics, etc.

Categories

  • AI News, Research & Latest Updates
  • Trending
  • Data Structures
  • Web Developement
  • Data Science

Important Subjects

  • Python Assignment Help
  • C++ Help
  • R Programming Help
  • Java Homework Help
  • Programming Help

Resources

  • About Us
  • Contact Us
  • Editorial Policy
  • Privacy Policy
  • Terms and Conditions

Website listed on Ecomswap. © Copyright 2025 All Rights Reserved.

No Result
View All Result
  • AI News
  • Data Structures
  • Web Developement
  • AI Code Generator
  • Student Help
  • Main Website

Website listed on Ecomswap. © Copyright 2025 All Rights Reserved.