70. 爬楼梯(进阶)
思路:
1. dp数组及其下标的含义:dp[i] 表示当爬到有i个台阶的楼顶,有 dp[i] 种方法;
2. 递推公式:求装满背包(楼梯)有几种方法,递推公式一般为 dp[i] += dp[i-nums[j]];
3. 初始化:dp[0] = 1;
4. 遍历顺序:本题求排列数,先遍历bagSize(楼梯),再遍历nums[i](每次爬的台阶数);
class Solution {
public int climbStairs(int n) {
int[] dp = new int[n+1];
int[] nums = {1,2};
dp[0] = 1;
for(int i=1;i<=n;i++){//i遍历bagSize
for(int j=0;j<nums.length;j++){//j遍历物品
if(i-nums[j]>=0) dp[i] += dp[i-nums[j]];
}
}
return dp[n];
}
}
322. 零钱兑换
思路:
1. dp数组及其下标的含义:dp[j]表示凑足总额为j所需钱币的最少个数为dp[j];
2. 递推公式:当j>=coins[i]时,dp[j] = dp[j-coins[i]]+1;由于 dp[j] 要取最小值,所以 dp[j] = Math.min(dp[j],dp[j-coins[i]+1);
3. 初始化:dp[0] = 0;其他下标的 dp[j] 则初始化为一个最大的数,以防比较过程中被覆盖;
4. 遍历顺序:本题并不强调求组合数还是排列数,因此两种遍历顺序均可。此处,采取遍历顺序为:coins(物品)放在外循环,amount(背包)在内循环。且内循环正序。
class Solution {
public int coinChange(int[] coins, int amount) {
int max = Integer.MAX_VALUE;
int[] dp = new int[amount+1];
for(int j=1;j<dp.length;j++){
dp[j]=max;
}
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];
}
}
279.完全平方数
思路:
1. 完全平方数就是物品(可以无限件使用),要凑的正整数n就是背包,那么题目可以转化为,凑满这个背包最少有多少物品?
2. dp数组及其下标的含义:dp[j]代表和为j的完全平方数的最少数量为dp[j];
3. 递推公式:dp[j] 可以由 dp[j-i*i] 推出,dp[j-i*i] +1 即可得到一个dp[j];由于要取最小值,dp[j] = Math.min(dp[j],dp[j-i*i]+1);
4. 初始化:dp[0] = 0;非0下标的dp[j]则初始化为最大值;
5. 遍历顺序:由于本题并不强调求组合数还是排列数,因此两种遍历顺序均可;
class Solution {
public int numSquares(int n) {
int max = Integer.MAX_VALUE;
int[] dp = new int[n+1];
for(int j=1;j<dp.length;j++){
dp[j] = max;
}
for(int j=1;j<=n;j++){
for(int i=1;i*i<=j;i++){
dp[j]=Math.min(dp[j],dp[j-i*i]+1);
}
}
return dp[n];
}
}