1. 爬楼梯
背包容量 n
物品 1 2 可以选择多次
求排列方式的数量
需将target放在外循环,将nums放在内循环。
即先确定target值,nums的取法随意
背包为外循环且正向遍历,物品为内循环
class Solution {
public int climbStairs(int n) {
// 背包容量 n
// 物品 1 2 可以选择多次
int[] dp = new int[n+1]; // 爬n阶有dp种方法
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];
}
}
2. 零钱兑换
class Solution {
public int coinChange(int[] coins, int amount) {
// amount 背包
// coins 物品 可以重复取 完全背包 正向遍历
int[] dp = new int[amount+1]; // dp[j] 容量为j时的最少个数(不是组合数)
int max = Integer.MAX_VALUE;
for (int j = 0; j < dp.length; j++) {
dp[j] = max;
}
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 - coins[i]] + 1, dp[j]); //取,不取
}
}
return dp[amount] == max ? -1 : dp[amount];
}
}
3. 完全平方数
物品是小于target的完全平方数
class Solution {
public int numSquares(int n) {
// n 背包
// 完全平方数 物品 可以重复取 完全背包 正向遍历
int[] dp = new int[n+1]; // dp[j] 容量为j时的最少个数(不是组合数)
int max = Integer.MAX_VALUE;
for (int j = 0; j < dp.length; j++) {
dp[j] = max;
}
dp[0] = 0; // 最少个数(不是方式数量)
for(int i = 1; i * i <= n; i++){ // 物品 i*i
for(int j = i*i; j <= n; j++) // 背包要大于i*i
if (dp[j - i*i] != max) { // 可以省略,因为一定能凑成, 凑 1*1 一定行
dp[j] = Math.min(dp[j - i*i] + 1, dp[j]); //取,不取
}
}
return dp[n];
}
}