Hey all, time for some dynamic programming! I've tried and failed, apparently I still don't understand the concept well enough to modify this the way I want.
Code I'm working with is from here: Java:: Coin Change Problem - dynamic programming - memoization - recursion

Basically I want the method to return not only the minimum number of coins needed (already works), but also the values of those coins. Sounds simple, but I'm stumped. Only thing I've changed is changing Hashtable to HashMap. Massive thanks to anyone who can help
public static HashMap<Integer, Integer> solved = new HashMap<Integer, Integer>();
 
 public static int kovanci(int[] k, int val) {
  // we've reached the end of recursion - a leaf
  // if the value is less than zero it means that the current combination is not solvable
  // if the value is zero, it means it is solvable
  if (val <= 0) return val;
 
  // for as many coins try to decrease the value for the coin value 
  // and try to solve the smaller problem
  int min = -1; //default: if it's not solvable
  for (int i = k.length - 1; i >= 0; i--) {
 
   // if the coin k[i] exists in the solution, it means the solution is
   // solutions(value - coin_value) + 1
   // eg. we have coins: 1, 3, 5 and the value is 11
   // if the coin 5 exists in the solution, try to solve the problem for value 11-5 = 6
   // the solution is smaller_solution + 1
   int newVal = val - k[i];
   int r;
 
   // dynamic programming - memoization
   // if we already have the minimum for the new value, fetch it (with time complexity O(1)), 
   // so that we don't recursively re-solve the problem and waste time
   if (solved.get(newVal) != null) {
    //solution = smaller_sollution + 1
    r = solved.get(newVal) + 1;
   } else {
    //try to solve the smaller problem
    r = kovanci(k, newVal);
    //if the solution is valid, the new solution is smaller_solution + 1
    if (r >= 0) r++;
    //else, keep the negative value - it means that it's not valid
    //eg: coins 3, 5, value 11 is not solvable, the solution is -1
   }
   // from all of the solutions, get the minimum value
   // and skip invalid solutions ( less than zero )
   if ((r > 0) && (min == -1 || r < min)) {
    min = r;
   }
  }
  // dynamic programming - memoization
  // once we do get the smallest possible solution, save it for later use
  // it saves A LOT of time and useless work, that's already been done
  solved.put(val, min);
  return min;
 }