2

I have a brute force solution with backtracking to solve the coin change problem. Currently i get minimum number of coins that can be used. But how could i also return the coins that were actually used? So for example if the amount is 100 then i would like to return [25, 25, 25, 25].

My current code is below:

public class Solution {

public static void main(String[] args) {
    Solution s = new Solution();

    int coinChange = s.coinChange(0, new int[] { 1, 25, 50 }, 100);
    System.out.println(coinChange);
}

public int coinChange(int idx, int[] coins, int amount) {
    if (amount == 0){
        return 0;
    }

    if (idx < coins.length && amount > 0) {
        int maxVal = amount / coins[idx];
        int minCost = Integer.MAX_VALUE;
        for (int x = 0; x <= maxVal; x++) {
            if (amount >= x * coins[idx]) {
                int res = coinChange(idx + 1, coins, amount - x * coins[idx]);
                if (res != -1)
                    minCost = Math.min(minCost, res + x);
            }
        }
        return (minCost == Integer.MAX_VALUE) ? -1 : minCost;
    }
    return -1;
}
}
Linny
  • 818
  • 1
  • 9
  • 22
donald tbd
  • 51
  • 5
  • You just need to track that alongside minCost, and change your minCost update line so that you know when you've changed minCost and also then update your minCoinsUsed too. Depending on your requirements you might want to store that as a list so that you can e.g. return multiple coin combinations when they all have the same length. – Rup Nov 28 '18 at 14:08
  • Actually is your question about how to pass this state around along with minCost, since you're passing that by returning it? You could pass an object by reference to all invocations of coinChange and store the state there, or since you have a new Solution object for every search you could even just store state in that. – Rup Nov 28 '18 at 14:12
  • Only need to return one result. Can you please post a code snippet by what you mean by tracking it alongside minCost? – donald tbd Nov 28 '18 at 14:13

1 Answers1

2

First of all, I suggest using accurate variable names. That will make it a lot easier for everyone, yourself included, to understand how the algorithm works. Your current array "coins" is not a list of coins, it is a list of available denominations, so it should named "denominations" or "denominations_available" or something like that. The variable you call "amount" is the amount remaining, so it should be named either "remaining" or amount_remaining".

To store the list of coins used so far, you can use a stack, or just a list that is treated like a stack. For example, you could use an ArrayList of Integers. Every time you call coinChange, add the denomination of the chosen coin (denominations[idx]) to your list before you make the call. Every time you return -1 (failure), remove the last item on the list (if there is one) before you return. When the success condition is reached (amount_remaining==0), the coin list will contain the coins used.

Correction: since coinChange is called multiple times in a loop, the stack must be popped after every call and the best minimum is pushed back again after it is determined. So, it should go like this:

int best_coin = 0;
for (int x = 0; x <= maxVal; x++) {
    if (amount >= x * coins[idx]) {
        <<<<<< PUSH GOES HERE
        int res = coinChange(idx + 1, coins, amount - x * coins[idx]);
        <<<<<< POP GOES HERE
        if (res == -1){ 
            // failed to find valid combination of coins
        } else {
            if( minCost < res + x ){
                // do nothing
            } else { // update minimum
                minCost = res + x;
                best_coin = coins[idx];
            }
        }
    }
    <<<<<< PUSH BEST COIN
return (minCost == Integer.MAX_VALUE) ? -1 : minCost;
Tyler Durden
  • 11,156
  • 9
  • 64
  • 126
  • Sorry, im misunderstanding something. I created a static array list and before recursively calling coinChange() I add denominations[idx] to that list. Also before returning -1 im removing last element from list. The result i get at the end looks like this: "1, 26, 26, 26, 26, 1, 26, 26, 26, 26, 1, 26, 49, 26, 26, 26, 1, 26, 26, 26, 26" – donald tbd Nov 28 '18 at 14:45
  • @donaldtbd right, what i wrote is not exactly correct, i will update the answer – Tyler Durden Nov 28 '18 at 15:25