算法训练营第四十五天|70. 爬楼梯 (进阶)、322. 零钱兑换、279.完全平方数

43 阅读1分钟

70. 爬楼梯

之前是一般动规的思路,现在用完全背包的角度来思考一下这道题。

改为:一步一个台阶,两个台阶,三个台阶,.......,直到 m 个台阶。问有多少种不同的方法可以爬到楼顶呢?

这时爬楼梯就变成了一个背包容量为n的完全背包问题,每一步都可以选择从1到m不同的阶数向上爬,并且可以重复选取。原题即为 m = 2 的情况。

class Solution {
    public int climbStairs(int n) {
        int[] dp = new int[n + 1];
        dp[0] = 1;
        int m = 2;
        
        // 先走一步再走两步,和先走两步再走一步,方法是不同的,所以本题实际上是在求排列
        // 求排列就是先遍历背包再遍历物品
        for(int i = 0; i <= n; i++){
            for(int j = 1; j <= m; j++){
                if(i - j >= 0)dp[j] += dp[i - j];
            }
        }
        return dp[n];
    }
}

322. 零钱兑换

class Solution {
    public int coinChange(int[] coins, int amount) {
        // dp[i]: 凑成总金额为i所需的最少硬币个数为i
        int[] dp = new int[amount + 1];

        for(int i = 1; i <= amount; i++)dp[i] = Integer.MAX_VALUE;
        dp[0] = 0;

        for(int i = 0; i < coins.length; i++){
            for(int j = coins[i]; j <= amount; j++){
                if(dp[j - coins[i]] != Integer.MAX_VALUE)dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
            }
        }

        return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount];
    }
}

279. 完全平方数

class Solution {
    public int numSquares(int n) {
        // dp[j]:和为j的完全平方数的最少数量为dp[j]
        int[] dp = new int[n + 1];
        Arrays.fill(dp, Integer.MAX_VALUE);
        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 - i * i] + 1, dp[j]);
            }
        }

        return dp[n];
    }
}