70. 爬楼梯(进阶版)
一步一个台阶,两个台阶,三个台阶,…,直到 m个台阶。问有多少种不同的方法可以爬到楼顶呢?
1阶,2阶,… m阶就是物品,楼顶就是背包。
每一阶可以重复使用,例如跳了1阶,还可以继续跳1阶。
问跳到楼顶有几种方法其实就是问装满背包有几种方法。 求的是排列
class Solution {
public int climbStairs(int n) {
int[] dp = new int[n + 1];
int m = 2; //m表示最多可以爬m个台阶
dp[0] = 1;
for (int i = 1; i <= n; i++) { // 遍历背包
for (int j = 1; j <= m; j++) { //遍历物品
if (i >= j) //當前的背包容量 大於 物品重量的時候,我們才需要記錄當前的這個裝得方法(方法數+)
dp[i] += dp[i - j];
}
}
return dp[n];
}
}
322. 零钱兑换
力扣题目链接
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
你可以认为每种硬币的数量是无限的。
示例 1:
- 输入:coins = [1, 2, 5], amount = 11
- 输出:3
- 解释:11 = 5 + 5 + 1
示例 2:
- 输入:coins = [2], amount = 3
- 输出:-1
示例 3:
- 输入:coins = [1], amount = 0
- 输出:0
示例 4:
- 输入:coins = [1], amount = 1
- 输出:1
示例 5:
- 输入:coins = [1], amount = 2
- 输出:2
提示:
1.确定dp数组以及下标的含义
背包容量: 目标值
硬币:物品
问:装满这个背包,最少用多少件物品
dp[j]:凑足总额为j所需钱币的最少个数为dp[j]
2.确定递推公式
Math.min
dp[j]=Math.min(dp[j],dp[j-coins[i]]+1)
3.初始化
首先凑足总金额为0所需钱币的个数一定是0,那么dp[0] = 0;
其他下标对应的数值呢?
考虑到递推公式的特性,dp[j]必须初始化为一个最大的数,否则就会在Math.min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖。
所以下标非0的元素都是应该是最大值。
//初始化dp数组为最大值
for (int j = 0; j < dp.length; j++) {
dp[j] = Integer.MAX_VALUE;
}
4.遍历顺序求
求最小的元素数量 ,不影响 都可以
5.打印dp数组
以输入:coins = [1, 2, 5], amount = 5为例
代码:
class Solution {
public int coinChange(int[] coins, int amount) {
int[] dp=new int[amount+1];
//初始化 其他下标 因为要求最小所以不能赋值为0 会被覆盖
for (int j = 0; j < dp.length; j++) {
dp[j] = 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 - coins[i]]是初始值则跳过
dp[j]=Math.min(dp[j],dp[j-coins[i]]+1);
}
}
}
return dp[amount]==Integer.MAX_VALUE?-1:dp[amount];
}
}
279.完全平方数
力扣题目链接
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。
示例 1:
- 输入:n = 12
- 输出:3
- 解释:12 = 4 + 4 + 4
示例 2:
- 输入:n = 13
- 输出:2
- 解释:13 = 4 + 9
提示:
1.确定dp数组的含义
背包容量: 整数n
物品:完全平方数 i*i
问题:给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。
dp[j]: 和为j时,完全平方数最少的数量为dp[j]
2.确定递推公式
dp[j]=Math.min(dp[j],dp[j-i*i]+1)
每个元素的数值用i*i表示
3.初始化
首先凑足总金额为0所需钱币的个数一定是0,那么dp[0] = 0;
其他下标对应的数值呢?
考虑到递推公式的特性,dp[j]必须初始化为一个最大的数,否则就会在Math.min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖。
所以下标非0的元素都是应该是最大值。
//初始化dp数组为最大值
for (int j = 0; j < dp.length; j++) {
dp[j] = Integer.MAX_VALUE;
}
4.遍历顺序求
求最小的元素数量,不影响
5.打印dp数组
已输入n为5例,dp状态图如下:
dp[0] = 0 dp[1] = min(dp[0] + 1) = 1 dp[2] = min(dp[1] + 1) = 2 dp[3] = min(dp[2] + 1) = 3 dp[4] = min(dp[3] + 1, dp[0] + 1) = 1 dp[5] = min(dp[4] + 1, dp[1] + 1) = 2
最后的dp[n]为最终结果。
代码:
class Solution {
public int numSquares(int n) {
int[] dp=new int[n+1];
for(int j=0;j<=n;j++){
dp[j]=Integer.MAX_VALUE;
}
dp[0]=0;
for(int i=1;i*i<=n;i++){ //遍历物品
for(int j=i*i;j<=n;j++){ //遍历背包 背包从物品大小开始
dp[j]=Math.min(dp[j],dp[j-i*i]+1); //为了下标不出现负数
}
}
return dp[n];
}
}