518 coin change II (01背包)
https://leetcode.com/problems/coin-change-ii/
这里讲得更清楚,得仔细研究下,代表了一大类问题,细分包括物品可不可以重复,以及dp matrix的压缩
class Solution {
public int change(int amount, int[] coins) {
// dp[i]是amount为i的放法数量
int[] dp = new int[amount+1];
// 注意初始化
dp[0] = 1;
for (int i = 0; i < coins.length; i++) {
// 一定是正序遍历,这样之前得到的dp[j]值能累加到之后dp[j]上,也就保证了能重复拿无数个
for (int j = coins[i]; j <= amount; j++) {
// 其实是做了dp array的压缩,本应该是二维数组dp[i][j]表示拿了coin i的时候amount为j的放法
// 本应该是dp[i][j] = dp[i-1][j](不拿这个硬币) + dp[i-1][j-coins[i]](拿这个硬币)
//放法 //之前coin在相同amount下积累的放法
dp[j] = dp[j] + dp[j-coins[i]];
//之前coin在去掉一个coins[i]之后积累的放法
//由于j在自增,所有j都减去了coins[i],
//所以之后的j能累积到之前j使用了coins[i]的放法,保证了coin无限
//比如coin为1,那么j为1时放法加上了dp[1-1]=dp[0]=1,
//当j为2时放法中会加上dp[2-1]=dp[1]也就是j为1时候的放法,
//其中就包含了dp[1-1]的放法,依次累加下去
//如果用二维数组则不需要担心顺序问题
}
}
return dp[amount];
}
}如果用二维做法是这样的
Last updated