70 爬楼梯 (进阶)
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 <= m; j++) { // 遍历物品
if (i - j >= 0) dp[i] += dp[i - j];
}
}
return dp[n];
}
};
322 零钱兑换
题目链接:322
思路:完全背包问题。
- 数组
dp[j]
代表装满背包容量j
所需的最少硬币数。 - 装满
j-coins[i]
需要的最少数量为dp[j-coins[i]]
,此时再加一枚硬币,即可装满,为了取最小,因此需考虑所有dp[j-coins[i]]+1
中最小的,即递推公式dp[j]=min(dp[j], dp[j-coins[i]]+1)
。 - 凑足金额0所需硬币为0,因此
dp[0]=0
,为了后续将初始值覆盖,其他初始化为INT_MAX
。 - 不强调组合还是排列,因此先遍历背包或先遍历物品都行。
代码:
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount+1, INT_MAX);
dp[0] = 0;
for (int i=0; i<coins.size(); ++i) {
for (int j=coins[i]; j<=amount; ++j) {
if (dp[j-coins[i]] < INT_MAX) dp[j] = min(dp[j], dp[j-coins[i]]+1);
}
}
return dp[amount]<INT_MAX ? dp[amount] : -1;
}
};
279 完全平方数
题目链接:279
思路:完全背包问题。与322 零钱兑换类似。
代码:
class Solution {
public:
int numSquares(int n) {
vector<int> dp(n+1, INT_MAX);
dp[0] = 0;
for (int i=1; i<=floor(sqrt(n)); ++i) {
for (int j=i*i; j<=n; ++j) {
dp[j] = min(dp[j], dp[j-i*i]+1);
}
}
return dp[n];
}
};