70.爬楼梯(进阶)
解题思路:
class Solution {
public int climbStairs(int n) {
/**
* 还有一种题目的理解方式,数字n可以分为多少种由1和2组成的排列
* 1.dp[j] 凑够j一共有多少种方案
* 2.dp[j] = dp[j] + dp[j - step[i]];
* 3.dp[0] = 1
* 4.完全背包:正向循环
*/
int[] step = new int[]{1,2};
int[] dp = new int[n + 1];
dp[0] = 1;
for(int j = 0; j <= n; j++){
for(int i = 0; i < step.length; i++){
if(j >= step[i]) dp[j] = dp[j] + dp[j - step[i]];
}
}
return dp[n];
}
}
322.零钱兑换
解题思路:
这个题需要注意的点就是,初始化为什么全都赋值成最大值.
因为这个题要求最少的硬币个数,体现在递推关系式中,就是要求两者之中最小的,如果初始化的时候都初始化为0,那么不管怎么比较,结果都为0,就导致,dp数组递推到最后都是0.所以初始化的时候要全初始化为最大值,只有最初的dp[0] = 0 才初始化为0.
class Solution {
public int coinChange(int[] coins, int amount) {
/**
* 1.dp[j] 凑成数字j最少需要多少个硬币
* 2.dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1)
* 3.dp[0] = 0;
* 4.不限制硬币使用数量,完全背包正向循环
*/
int[] dp = new int[amount + 1];
Arrays.fill(dp,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);
}
}
}
if(dp[amount] == Integer.MAX_VALUE) return -1;
return dp[amount];
}
}
279.完全平方数
题目链接:279. 完全平方数 - 力扣(LeetCode)
解题思路:
该题目的物品就是每个完全平方数,完全没有必要先将完全平方数都算出来存起来,直接利用外层循环的index就可以了。
因为是求最少个数的完全背包问题,所以初始化的时候,除了第一个元素初始化为真实值0,其他元素都初始化成Integer.MAX_VALUE,同时在递推dp数组的时候,要在外面嵌套一层if判断,确认要比较的元素是否是初始化时候的值,如果是,就代表目前还没有完全平方数能够组合出该数字,就不和dp[j]进行比较了。如果不是,再与dp[j]进行比较取最小。
class Solution {
public int numSquares(int n) {
/**
* 这个题和零钱兑换是类似的,都是要返回最小组成数字的个数。
* 1.dp[j] 和为n的完全平方数的最小数量
* 2.dp[j] = Math.min(dp[j], dp[j - Math.pow(i,2)] + 1)
* 3.dp[0] = 0; dp[j] = Integer.MAX_VALUE
* 4.完全背包问题正向遍历
*/
int[] dp = new int[n + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for(int i = 1; i <= n; i++){
int k = (int)Math.pow(i,2);
for(int j = k; j <= n; j++){
if(dp[j - k] != Integer.MAX_VALUE){
dp[j] = Math.min(dp[j], dp[j - k] + 1);
}
}
}
return dp[n];
}
}