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

题目链接:70. 爬楼梯 (进阶)

代码随想录

 我们不是仅仅就走2个,或个3个,而是我们一步可以走一个,两个,3个,4个,一直到m个,这个时候我们,并且到达每个台阶都可以走1-m个台阶,这个时候就需要利用完全背包;

一共有n阶台阶,每一个我们都可以走1-m台阶,我们有m件物品,值1-m;

问跳到楼顶有多少方法,就是问装满背包有多少方法;

动态规划五部曲:

1:确定dp含义

dp[i] 爬到有i个台阶的楼顶的方法有dp[i];

2,确定递推公式;

求装满背包有多少方法,我们用的是dp[j] += dp[j - nums[i]];

在这道题中,我们就是dp[i] += dp[i - j]

3,初始化,第一个肯定不能为0,因为后面的是由前面的推出来的,如果dp[0] = 0,那么后面的全为0;所以dp[1] = 1;

4,遍历顺序;

先遍历物品,再遍历背包,这样求的是组合数,

先遍历背包,再遍历物品,这样求的是排列数;

这道题我们是求排列,因为先走1个台阶,再走2个台阶到楼顶和先走2个台阶,再走一个台阶到楼顶是不一样的,所以我们求的是排列;

那么我们就先遍历背包,再遍历物品;

class Solution {
    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(j >= i) dp[j] += dp[j - i];
        }
        return dp[n];
    }
}

题目链接:322. 零钱兑换  

视频讲解:动态规划之完全背包,装满背包最少的物品件数是多少?| LeetCode:322.零钱兑换_哔哩哔哩_bilibili

代码随想录

看完代码随想录之后的想法:

是完全背包

五部曲;

1,确定dp的含义;

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

2, 确定递推公式

dp[j] 等于dp[j - coins[i]] + 1;我们需要求它们最小的一个;

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

3,dp数组的初始化;

因为要求最小值,肯定是初始化最大的;

4,遍历顺序都可以,这个不是求装满背包有几种方式,自然就不需要考虑是否排列,还是组合了;我们求的是硬币的个数,那么有顺序无顺序都不影响结果,即无论排列还是组合都可以;

class Solution {
    public int coinChange(int[] coins, int amount) {
        int max = Integer.MAX_VALUE;
        int[] dp = new int[amount + 1];
        //初始化dp数组为最大值
        for (int j = 0; j < dp.length; j++) {
            dp[j] = max;
        }
        //当金额为0时需要的硬币数目为0
        dp[0] = 0;
        for (int i = 0; i < coins.length; i++) {
            //正序遍历:完全背包每个硬币可以选择多次
            for (int j = coins[i]; j <= amount; j++) {
                //只有dp[j-coins[i]]不是初始最大值时,该位才有选择的必要
                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.完全平方数

本题 和 322. 零钱兑换 基本是一样的,大家先自己尝试做一做 

视频讲解:动态规划之完全背包,换汤不换药!| LeetCode:279.完全平方数_哔哩哔哩_bilibili

代码随想录

class Solution {
    // 版本一,先遍历物品, 再遍历背包
    public int numSquares(int n) {
        int max = Integer.MAX_VALUE;
        int[] dp = new int[n + 1];
        //初始化
        for (int j = 0; j <= n; j++) {
            dp[j] = max;
        }
	//如果不想要寫for-loop填充數組的話,也可以用JAVA內建的Arrays.fill()函數。
	//Arrays.fill(dp, Integer.MAX_VALUE);
	
        //当和为0时,组合的个数为0
        dp[0] = 0;
        // 遍历物品
        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);
                //}
		//不需要這個if statement,因爲在完全平方數這一題不會有"湊不成"的狀況發生( 一定可以用"1"來組成任何一個n),故comment掉這個if statement。
            }
        }
        return dp[n];
    }
}

你可能感兴趣的:(代码随想录算法训练营,算法,矩阵,leetcode)