
问题分析:完全背包问题,且求的是最值,并且需要达到恰好装满容量为amount的背包。
解法一(最朴素)
注:由于没有进行下标填充,所以初始化过程需要特殊处理
class Solution {public int coinChange(int[] coins, int amount) {int n = coins.length;int[][] dp = new int[n][amount + 1];int INF = 0x3f3f3f;//初始化for(int i = 0; i < n; i++){Arrays.fill(dp[i], INF);}//特殊处理 coins[0]物品的情况dp[0][0] = 0;for(int j = 1; j <= amount; j++){dp[0][j] = j % coins[0] == 0 ? j / coins[0] : INF;}for(int i = 1; i < n; i++){int val = coins[i];for(int j = 0; j <= amount; j++){for(int k = 0; k * val <= j; k++){dp[i][j] = Math.min(dp[i][j], dp[i - 1][j - k * val] + k);}}}return dp[n-1][amount] == INF ? -1 : dp[n-1][amount];}}
解法二(下标填充)
注:进行下标填充,初始化的过程简化了
class Solution {public int coinChange(int[] coins, int amount) {int n = coins.length;int[][] dp = new int[n + 1][amount + 1];int INF = 0x3f3f3f;for(int i = 0; i <= n; i++){Arrays.fill(dp[i], INF);}dp[0][0] = 0;for(int i = 1; i <= n; i++){int val = coins[i - 1];for(int j = 0; j <= amount; j++){for(int k = 0; k * val <= j; k++){dp[i][j] = Math.min(dp[i][j], dp[i - 1][j - k * val] + k);}}}return dp[n][amount] == INF ? -1 : dp[n][amount];}}
解法三(一维)
注:完全背包的二维解法到一维解法,可以降低时间复杂度,一维解法的时间复杂度为O(N * C)
class Solution {
public int coinChange(int[] coins, int amount) {
int n = coins.length;
int[] dp = new int[amount + 1];
int INF = 0x3f3f3f;
Arrays.fill(dp, INF);
dp[0] = 0;
for(int i = 1; i <= n; i++){
int val = coins[i - 1];
for(int j = 0; j <= amount; j++){
int a = dp[j];
int b = j - val >= 0 ? dp[j - val] + 1 : INF;
dp[j] = Math.min(a, b);
}
}
return dp[amount] == INF ? -1 : dp[amount];
}
}
