Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * The coin change problem is an unbounded knapsack problem variant. The problem asks you to find
- * the minimum number of coins required for a certain amount of change given the coin denominations.
- * You may use each coin denomination as many times as you please.
- *
- * <p>Tested against: https://leetcode.com/problems/coin-change/
- *
- * @author William Fiset, [email protected]
- */
- import java.util.*;
- public class CoinChange {
- private static final int INF = 987654321;
- public static int coinChange(int[] coins, int amount) {
- if (coins == null) throw new IllegalArgumentException("Coins array is null");
- if (coins.length == 0) throw new IllegalArgumentException("No coin values :/");
- final int N = coins.length;
- // Initialize table and set first row to be infinity
- int[][] DP = new int[N + 1][amount + 1];
- java.util.Arrays.fill(DP[0], INF);
- DP[1][0] = 0;
- // Iterate through all the coins
- for (int i = 1; i <= N; i++) {
- int coinValue = coins[i - 1];
- for (int j = 1; j <= amount; j++) {
- // Consider not selecting this coin
- DP[i][j] = DP[i - 1][j];
- // Try selecting this coin if it's better
- if (j - coinValue >= 0 && DP[i][j - coinValue] + 1 < DP[i][j])
- DP[i][j] = DP[i][j - coinValue] + 1;
- }
- }
- // The amount we wanted to make cannot be made :/
- if (DP[N][amount] == INF) return -1;
- // Return the minimum number of coins needed
- return DP[N][amount];
- }
- public static int coinChangeSpaceEfficient(int[] coins, int amount) {
- if (coins == null) throw new IllegalArgumentException("Coins array is null");
- // Initialize table and set everything to infinity except first cell
- int[] DP = new int[amount + 1];
- java.util.Arrays.fill(DP, INF);
- DP[0] = 0;
- for (int i = 1; i <= amount; i++)
- for (int coinValue : coins)
- if (i - coinValue >= 0 && DP[i - coinValue] + 1 < DP[i]) DP[i] = DP[i - coinValue] + 1;
- // The amount we wanted to make cannot be made :/
- if (DP[amount] == INF) return -1;
- // Return the minimum number of coins needed
- return DP[amount];
- }
- // The recursive approach has the advantage that it does not have to visit
- // all possible states like the tabular approach does. This can speedup
- // things especially if the coin denominations are large.
- public static int coinChangeRecursive(int[] coins, int amount) {
- if (coins == null) throw new IllegalArgumentException("Coins array is null");
- if (amount < 0) return -1;
- int[] DP = new int[amount + 1];
- return coinChangeRecursive(amount, coins, DP);
- }
- // Private helper method to actually go the recursion
- private static int coinChangeRecursive(int amount, int[] coins, int[] DP) {
- // Base cases.
- if (amount < 0) return -1;
- if (amount == 0) return 0;
- if (DP[amount] != 0) return DP[amount];
- int minCoins = INF;
- for (int coinValue : coins) {
- int newAmount = amount - coinValue;
- int value = coinChangeRecursive(newAmount, coins, DP);
- if (value != -1 && value < minCoins) minCoins = value + 1;
- }
- // If we weren't able to find some coins to make our
- // amount then cache -1 as the answer.
- return DP[amount] = (minCoins == INF) ? -1 : minCoins;
- }
- public static void main(String[] args) {
- Scanner input = new Scanner(System.in);
- System.out.print("Total Coins: ");
- int totalCoins = input.nextInt();
- int[] coins = new int[totalCoins];
- System.out.print("Coin denomination: ");
- for(int i = 0; i < totalCoins; i++)
- {
- try{
- coins[i] = input.nextInt();
- }
- catch(InputMismatchException e){
- System.out.println("Input not recognized");
- break;
- }
- catch(ArrayIndexOutOfBoundsException e){
- System.out.println("Coins Total is out of bounds");
- }
- catch(Exception e){
- throw new IllegalArgumentException(e);
- }
- }
- try{
- System.out.print("Change given: ");
- int amount = input.nextInt();
- System.out.println("Minimum coins needed");
- System.out.printf("a. First solution: %d\n", coinChange(coins, amount));
- System.out.printf("b. Space efficient solution: %d\n",
- coinChangeSpaceEfficient(coins, amount));
- System.out.printf("c. Recursive solution: %d\n",
- coinChangeRecursive(coins, amount));
- }
- catch(InputMismatchException e){
- throw new InputMismatchException("Input not recognized");
- }
- finally{
- System.out.println("Program Finished");
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment