算法刷题 Day 45 | ● 70. 爬楼梯 (进阶) ● 322. 零钱兑换 ● 279.完全平方数
70. 爬楼梯 (进阶)
这道题目 爬楼梯之前我们做过,这次再用完全背包的思路来分析一遍
Tips:
改为:一步一个台阶,两个台阶,三个台阶,.......,直到 m个台阶。问有多少种不同的方法可以爬到楼顶呢?
1阶,2阶,.... m阶就是物品,楼顶就是背包。
每一阶可以重复使用,例如跳了1阶,还可以继续跳1阶。
问跳到楼顶有几种方法其实就是问装满背包有几种方法。
此时大家应该发现这就是一个完全背包问题了!
我的题解:
class Solution {
public:
int climbStairs(int n) {
// 完全背包版代码
vector<int> dp(n+1,0);
dp[0] = 1;
for(int i = 1; i<=n; i++){
for(int j = 1; j<=2; j++){
if(i>=j){
dp[i] += dp[i-j];
}
}
}
return dp[n];
}
};
322. 零钱兑换
如果求组合数就是外层for循环遍历物品,内层for遍历背包。
如果求排列数就是外层for遍历背包,内层for循环遍历物品。
这句话结合本题 大家要好好理解。
视频讲解:https://www.bilibili.com/video/BV14K411R7yv
https://programmercarl.com/0322.%E9%9B%B6%E9%92%B1%E5%85%91%E6%8D%A2.html
Tips:想好思路后写出代码,就很简单了。
本题求钱币最小个数,那么钱币有顺序和没有顺序都可以,都不影响钱币的最小个数。
所以本题并不强调集合是组合还是排列。
我的题解:
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount+1,INT_MAX);
dp[0] = 0;
for(int i = 1; i<= amount; i++){
for(int j = 0; j<coins.size(); j++){
if(i-coins[j] >=0 && dp[i -coins[j]] != INT_MAX){
dp[i] = min(dp[i],dp[i-coins[j]]+1);
}
}
}
if(dp[amount] == INT_MAX){
return -1;
}
return dp[amount];
}
};
279.完全平方数
本题 和 322. 零钱兑换 基本是一样的,大家先自己尝试做一做
视频讲解:https://www.bilibili.com/video/BV12P411T7Br
https://programmercarl.com/0279.%E5%AE%8C%E5%85%A8%E5%B9%B3%E6%96%B9%E6%95%B0.html
Tips:要记得初始化dp[0]啊,同时代码中进行了一个剪枝的操作
我的题解:
class Solution {
public:
int numSquares(int n) {
vector<int> dp(n+1,INT_MAX);
dp[0] = 0;
for(int i = 0; i <= n/2 + 1; i++){ // 这里有剪枝,+1是为了n = 1的情况
for(int j = i*i; j<=n; j++){
if(dp[j - i*i] != INT_MAX){
dp[j] = min(dp[j], dp[j-i*i]+1);
}
}
}
if(dp[n]==INT_MAX){
return -1;
}
return dp[n];
}
};

浙公网安备 33010602011771号