力扣322题、279题(完全背包)

322、零钱兑换

基本思想:

每种硬币的数量是无限的------完全背包

与518题不同,518问的是方法种类,本题问的是硬币个数

具体实现:

1.确定dp数组以及下标的含义

dp[j]:凑足总额为j所需钱币的最少个数为dp[j]

2.确定递推公式

完全背包公式:

 dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

本题:dp[j] = min(dp[j],dp[j - coins[i]] + 1);

对应到背包问题上硬币面值是物品重量,一个硬币的数量对应物品价值

3.dp数组初始化

凑足总金额为0所需钱币的个数一定是0,那么dp[0] = 0;

考虑到递推公式的特性,dp[j]必须初始化为一个最大的数,否则就会在min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖。

所以下标非0的元素都是应该是最大值。

4.确定遍历顺序

本题的两个for循环的关系是:外层for循环遍历物品,内层for遍历背包或者外层for遍历背包,内层for循环遍历物品都是可以的

从前向后

5.举例

代码:

class Solution {
    public int coinChange(int[] coins, int amount) {
        int max = Integer.MAX_VALUE;
        int[] dp = new int[amount + 1];
        for (int j = 1; j < dp.length; j++){
            dp[j] = max;
        }
        dp[0] = 0;
        for (int i = 0; i < coins.length; i++){
            for (int j = coins[i]; j <= amount; j++){
                if (dp[j - coins[i]] != max){
                    dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
                }
            }
        }
        return dp[amount] == max ? -1:dp[amount];
    }
}

279、完全平方数

基本思想:

完全平方数就是物品(可以无限件使用),凑个正整数n就是背包,问凑满这个背包最少有多少物品?

具体实现:

1.确定dp数组以及下标的含义

dp[i]:和为i的完全平方数的最少数量为dp[i]

2.确定递推公式

dp[j] = min(dp[j - i * i] + 1, dp[j])

3,.初始化

dp[0]表示 和为0的完全平方数的最小数量,dp[0] = 0

从递推公式dp[j] = min(dp[j - i * i] + 1, dp[j]);中可以看出每次dp[j]都要选最小的,

所以非0下标的dp[i]一定要初始为最大值,这样dp[j]在递推的时候才不会被初始值覆盖。

4.确定遍历顺序

两层for循环内外顺序随便

从前到后

5.举例推导

代码:

class Solution {
    public int numSquares(int n) {
        int max = Integer.MAX_VALUE;
        int[] dp = new int[n + 1];
        for (int j = 1; j <= n; j++){
            dp[j] = max;
        }
        for (int i = 1; i * i <= n; i++){
            for (int j = i * i; j <= n; j++){
                if (dp[j - i * i] != max) {
                    dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
                }
            }
        }
        return dp[n];
    }
}
原文地址:https://www.cnblogs.com/zhaojiayu/p/15659303.html