代码随想录-2023/08/13

118 阅读2分钟

背包问题

70.爬楼梯

解题思路:

  1. 斐波那契数列 --- dp[i] = dp[i-1] + dp[i-2]
  2. 完全背包问题: 假设物品有两个 (一步和两步), 每种物品无限个, 现问装完背包为n的可以有多少种不同的方案?
  3. 完全背包: 求不同排列, 故外层背包, 内层物品, 背包升序遍历, 递推公式为dp[j] = dp[j] + dp[j-i]

代码:

    class Solution {
        // 假设背包容量为n, 物品有两个1和2, 每种物品有无限个
        // 请问背包装满的所有情况
        // 同时 先走1再走2 和先走2再走1 是两种不同的情况, 所以是求排列?
        public int climbStairs(int n) {
            int[] dp = new int[n + 1];
            dp[0] = 1;
            // 完全背包 --- 升序 --- 求排列:背包在外层遍历
            for(int j=1; j <= n; j++){
                // 遍历物品
                for(int i=1; i<=2; i++){
                    if(i <= j)
                    dp[j] = dp[j] + dp[j-i];
                }
            }
            return dp[n];
        }
    }

322.零钱兑换

解题思路: 硬币无限个, 完全背包问题

  1. 求最少硬币个数, 假设硬币价值为1, 此题即求装满背包的最小价值
  2. 求组合问题, 故外层遍历物品, 内层遍历背包
  3. 求最小价值, 且元素初始化为最大值, 并且dp[0] 初始化成0

代码:

class Solution {
    // 假设物品价值为1, 求最少的物品个数即就是求装满背包的最小价值
    public int coinChange(int[] coins, int amount) {
        int[] dp = new int[amount+1];
        Arrays.fill(dp, 0x7fffffff);
        dp[0] = 0;
        // 完全背包问题 --- 求最小价值 --- 求组合
        for(int i=0; i<coins.length; i++){
            for(int j=coins[i]; j<=amount; j++){
                if(dp[j-coins[i]] != 0x7fffffff){
                    dp[j] = Math.min(dp[j], dp[j-coins[i]] + 1);
                }
            }
        }
        // -1: 装不满背包
        return dp[amount] == 0x7fffffff ? -1:dp[amount];
    }
}

279.完全平方数

解题思路:

  1. 每个物品是完全平方数, 其为小于n的完全平方数
  2. 可以无限拿, 所以是完全背包问题
  3. 且求组和, 所以是外层物品, 内层背包
  4. 求最少个数, 假设物品价值为1, 即装满背包的最小价值
  5. 因为本题有1, 所以肯定能装满, 无需考虑装不满的情况

代码:

class Solution {
    // 因为本题有1, 所以肯定能装满, 无需考虑装不满的情况
    public int numSquares(int n) {
        // 完全背包问题 --- 求最小价值 --- 求组和(外层物品 & 内层背包)
        int[] dp = new int[n + 1];
        Arrays.fill(dp, 0x7fffffff);
        dp[0] = 0;
        // 遍历物品
        for(int i=1; i*i <= n; i++){
            // 遍历背包
            for(int j=i*i; j<=n; j++){
                dp[j] = Math.min(dp[j], dp[j-i*i] + 1);
            }
        }
        return dp[n];
    }
}