今天的重点还是理解排列和组合对于dp的不同操作, 和遍历顺序的区别, 同时添加了关于min的操作
爬楼梯(进阶)
想一想, 如果一步可以一个台阶, 两个台阶….m个台阶, 问有多少种方法可以爬到楼顶
可以发现, 爬台阶的次数可以无限次用, 所以其实也是个完全背包问题
class Solution {public int climbStairs(int n) {int[] dp = new int[n + 1];int[] weight = {1,2};dp[0] = 1;for (int i = 0; i <= n; i++) {for (int j = 0; j < weight.length; j++) {if (i >= weight[j]) dp[i] += dp[i - weight[j]];}}return dp[n];}
}
零钱兑换
这里问的是最小的硬币个数, 那么很妙的一点其实就是在递推公式里加个min的条件就行了
(细节: 需要给dp数组进行赋值;递推公式需满足条件: 如果是初始值就跳过)
class Solution {public int coinChange(int[] coins, int amount) {int[] dp = new int[amount + 1];//初始化最大值int max = Integer.MAX_VALUE;//为什么不能用增强for, 因为这就变成给取出来的数赋值, 而不是给数组赋for(int i = 0; i < dp.length; i++){dp[i] = max;}//初始化dp数组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];}
}
完全平方数
提议相当于: 完全平方数就是物品(可以无限使用), 凑个正整数n就是背包, 为凑满这个背包最少有多少个物品, 听起来和上一个零钱兑换一模一样
class Solution {public int numSquares(int n) {int max = Integer.MAX_VALUE;int[] dp = new int[n + 1];//这里也可以直接用<=n替代for(int i = 0; i < dp.length; i++){dp[i] = max;}//初始化:dp[0] = 0;//这里遍历从i开始就好, 因为0的平分还是0for(int i = 1; i*i <= n; i++){for(int j = i*i; j <= n; j++){//注意这里是判断dp数组if(dp[j - i*i] != max){//记得加一dp[j] = Math.min(dp[j], dp[j - i*i] + 1);}}}//这里直接return dp[n]就好return dp[n];}
}