Java recursive coin change attempt

Growler picture Growler · May 10, 2013 · Viewed 10k times · Source

I'm trying the java coin change problem to enumerate all possible sets of change to be given for n.

My logic follows as such:

while n >= denom m {
array[]+= denom m
n-= denom m
}
list.add[array[]]

return coinChanger(++denom)

My code:

public List<Integer> makeChange(int change) {

    int[] denominations;
    denominations = new int[]{1, 5, 10, 25};

    return changeMaker(change, denominations, 0);
}

public List<Integer> changeMaker(int change, int[] denominations, int index) {
    List<Integer> resultsList = new ArrayList<Integer>();
    int[] resultDenom;
    resultDenom = new int[4];

    if (change <= 1) {
        return resultsList;
    }

    while (change >= denominations[index]) {
        resultDenom[index] += denominations[index];
        System.out.println("ResultsDenom: " + resultDenom[index]);
        change -= denominations[index];
    }
    resultsList.add(resultDenom[index]);

    for (int val : resultDenom) {
        System.out.println(val);
    }


    if (change > denominations[index]) {    
        return changeMaker(change-=denominations[index], denominations, ++index);       

    }
    return resultsList;
}

This outputs just 1 set of all the enumerations:

OUTPUT:

27
0
0
0
RESULT CHANGE PERMUTATIONS LIST: [27]

Questions:

I'm struggling to figure out how move to the next denomination once one of them finishes... I know you're supposed to move to the next index in the denomination array... but then that just adds the next coin... how do I make it add the next largest coin, then recursively drop to the next coin... all the way through all 4 coins?

Thanks!

*EDIT**

public List<Integer> makeChange(int change) {

    int[] denominations;
    denominations = new int[]{25, 10, 5, 1};

    return changeMaker(change, denominations, 0);
}

public List<Integer> changeMaker(int change, int[] denominations, int index) {
    List<Integer> resultsList = new ArrayList<Integer>();
    int[] resultDenom;
    resultDenom = new int[4];

    if (change <= 1) {
        return resultsList;
    }

    if (index > 3) { 
        return resultsList;
    }
    //if 27 >= 25
    if (change >= denominations[index]) {   

        //[+25, 0, 0, 0]
        resultDenom[index] += denominations[index];

        //{  LIST  } <--- [25, 0, 0, 0]
                //List now contains { [25, 0, 0, 0], }, still need all other permutations
        resultsList.add(resultDenom[index]);

        //27 - 25, 
        return changeMaker(change-=denominations[index], denominations, ++index);       

    }
    return resultsList;
}

DESIRED OUTPUT: List of Lists... 27 cents:

LIST{ [1, 0, 0, 2], [0, 2, 1, 2], [0, 1, 3, 2]... etc}

Answer

Stefan Haustein picture Stefan Haustein · May 11, 2013

Simplest solution is to recurse into two variants at each step (if you are not finished):

  1. Continue with the current coin: Add it to the list and recurse.
  2. Switch to the next coin: Increment coin pos and recurse.

Should look like this:

public class Coins {
  static final int[] DENOMINATIONS = {25, 10, 5, 1};

  public static void change(int amount) {
    change(amount, new ArrayList<Integer>(), 0);
  }

  private static void change(int remaining, List<Integer> coins, int pos) {
    if (remaining == 0) {
      System.out.println(coins);
    } else {
      if (remaining >= DENOMINATIONS[pos]) {
        coins.add(DENOMINATIONS[pos]);
        change(remaining - DENOMINATIONS[pos], coins, pos);
        coins.remove(coins.size() - 1);
      }
      if (pos + 1 < DENOMINATIONS.length) {
        change(remaining, coins, pos + 1);
      }
    }
  }
}

If you want to collect the lists, you need to make a copy of the list where a coin is added (instead of removing it after returning from the call).