问题:
难度:easy
说明:
输入会给出一个amount 需要的总金额,coins 硬币的数值,要求返回多少种硬币组合方式,可以凑成这样一个 amount 金额。
这很明显的一个背包问题,同样可以用一个全排列方法。
相关问题:
全排列(https://blog.csdn.net/qq_28033719/article/details/105860028)
硬币和背包(https://blog.csdn.net/qq_28033719/article/details/106501253)
输入案例:
Example 1:
Input: amount = 5, coins = [1, 2, 5]
Output: 4
Explanation: there are four ways to make up the amount:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
Example 2:
Input: amount = 3, coins = [2]
Output: 0
Explanation: the amount of 3 cannot be made up just with coins of 2.
Example 3:
Input: amount = 10, coins = [10]
Output: 1
我的代码:
可以当做是一个完全背包问题,把背包容量当做amount,金额,把物体重量设定为硬币价格,不过价格设定为排列数这个需要理解一下。状态转换方程的话是:
amountarr[i][j] = amountarr[i][j] + amountarr[i][j - coins[i]];(j > w[i])
因为不用比较大小,只需要直接拿排列数就可以了,我的话直接写成一维的dp
class Solution {
public int change(int amount, int[] coins) {
int[] amountarr = new int[amount + 1];
amountarr[0] = 1;
int len = coins.length;
for(int i = 0;i < len;i ++) {
// 直接从coins[i]开始,减少计算次数
for(int j = coins[i];j <= amount;j ++) {
amountarr[j] = amountarr[j] + amountarr[j - coins[i]];
}
}
return amountarr[amount];
}
}
使用二维dp
class Solution {
public int change(int amount, int[] coins) {
int[][] amountarr = new int[coins.length + 1][amount + 1];
amountarr[0][0] = 1;
int len = coins.length;
for(int i = 0;i < len;i ++) {
amountarr[i + 1][0] = 1;
for(int j = 1;j <= amount;j ++) {
// 这里必须要从1开始,不然会丢失数据
amountarr[i + 1][j] = amountarr[i][j] + (j >= coins[i]?amountarr[i + 1][j - coins[i]] : 0);
}
}
return amountarr[coins.length][amount];
}
}