### Question:
CoinChangeSolution { public static int countOptimal(int[] coins, int amt) { int solutions[] = new int[amt + 1]; solutions[0] = 1; for (Integer i : coins) for (int j = i; j <= amt; j++) solutions[j] += solutions[j - i]; return solutions[amt]; }  static void main(String[] args); static int countOptimal(int[] coins, int amt); static int countRecursive(int coins[], int c, int sum); static void print();  }### Answer:
@Test public void testCoinChangeSolutionOptimal() { int coins[] = { 1, 2, 3 }; assertEquals(4, CoinChangeSolution.countOptimal(coins, 4)); coins = new int[] { 1, 2, 3 }; assertEquals(5, CoinChangeSolution.countOptimal(coins, 5)); coins = new int[] { 2, 5, 3, 6 }; assertEquals(5, CoinChangeSolution.countOptimal(coins, 10)); }
@Test public void testCoinChangeSolutionOptimalSpeed() { int coins[] = { 2, 5, 3, 6, 10, 7, 8, 12, 17, 19, 20 }; assertEquals(227491942, CoinChangeSolution.countOptimal(coins, 250)); }