Kinds of Coin Change
Problem & Approach
-
-
Let
dp[i][amount]
to be the fewest number of coins amongfrom 0 to i-th
coins that makes up toamount
. So,dp[i][amount] = min(dp[i - 1][amount](not use i-th coin), 1 + dp[i][amount - coins[i]](use i-th coin))
. More importantly, as fordp[i][amount]
could be updated bydp[i][amount - coins[i]]
rather thandp[i - 1][amount - coins[i]]
, that’s because every coin can be used for many times. -
To decrease the space complexity, we can make the
dp[i][amount]
to bedp[amount]
. Because every time, dp[i][amount] is updated only byi-th
subarray or(i-1)-th
subarray. So we only need to update dp[amount] with itself. Then, dp[amount] = min(dp[amount], dp[amount - coins[i]] + 1).
-
-
-
The idea is same as
Coin Change I
. Letdp[i][amount]
to be the number of combinations of usingfrom 0 to i-th
coins to makes up toamount
. So,dp[i][amount] = dp[i - 1][amount](not use i-th coin) + dp[i][amount - coins[i]](use i-th coin)
. -
To decrease the space complexity, we can make the
dp[i][amount]
to bedp[amount]
. So,dp[amount] = dp[amount] + dp[amount - coins[i]]
.
-
Code
- problem 1(version of larger space complexity)
class Solution { public int coinChange(int[] coins, int amount) { int N = coins.length; if(N == 0) { if(amount == 0) return 0; else return -1; } Arrays.sort(coins); int[][] dp = new int[N][amount + 1]; for(int i = 0; i < N; i ++){ dp[i][0] = 0; } for(int i = 1; i <= amount; i ++){ if(i % coins[0] == 0){ dp[0][i] = i / coins[0]; } else{ dp[0][i] = Integer.MAX_VALUE; } } for(int i = 1; i < N; i ++){ for(int j = 1; j <= amount; j ++){ dp[i][j] = dp[i - 1][j]; if(j >= coins[i] && dp[i][j - coins[i]] < Integer.MAX_VALUE) dp[i][j] = Math.min(dp[i][j], dp[i][j - coins[i]] + 1); } } return dp[N - 1][amount] == Integer.MAX_VALUE ? -1 : dp[N - 1][amount]; } }
- problem 1(version of smaller space complexity)
class Solution { public int coinChange(int[] coins, int amount) { int N = coins.length; if(N == 0) { if(amount == 0) return 0; else return -1; } int[] dp = new int[amount + 1]; Arrays.fill(dp, Integer.MAX_VALUE); dp[0] = 0; for(int i = 1; i <= N; i ++){ for(int j = 1; j <= amount; j ++){ if(j >= coins[i - 1] && dp[j - coins[i - 1]] < Integer.MAX_VALUE){ dp[j] = Math.min(dp[j], 1 + dp[j - coins[i - 1]]); } } } return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount]; } }
- problem 2(version of larger space complexity)
class Solution { public int change(int amount, int[] coins) { int N = coins.length; if(amount == 0){ return 1; } if(N == 0){ return 0; } int[][] dp = new int[N + 1][amount + 1]; for(int i = 0; i <= N; i ++){ dp[i][0] = 1; } for(int i = 1; i <= N; i ++){ for(int j = 1; j <= amount; j ++){ dp[i][j] = dp[i - 1][j]; if(j >= coins[i - 1]){ dp[i][j] += dp[i][j - coins[i - 1]]; } } } return dp[N][amount]; } }
- problem 2(version of smaller space complexity)
class Solution { public int change(int amount, int[] coins) { int N = coins.length; if(amount == 0){ return 1; } if(N == 0){ return 0; } int[] dp = new int[amount + 1]; dp[0] = 1; for(int i = 1; i <= N; i ++){ for(int j = 1; j <= amount; j ++){ if(j >= coins[i - 1]){ dp[j] += dp[j - coins[i - 1]]; } } } return dp[amount]; } }