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