第一题、爬楼梯 (进阶)力扣题目链接
抽象完全背包问题,然后弄清for循环顺序
class Solution {
public:int climbStairs(int n) {vector<int> dp(n+1, 0);dp[0] = 1; // 第一个初始为1,其他为0, 后续dp是根据 i-j求得for(int i=1; i <= n; i++){ // 遍历背包for(int j=1; j <= 2; j++){ // 遍历物品 (2改成m就可以升级为每步爬1-m级台阶)if(i - j >=0) dp[i] += dp[i-j];}}return dp[n];}
};
第二题、零钱兑换 力扣题目链接
如果求组合数就是外层for循环遍历物品,内层for遍历背包。
如果求排列数就是外层for遍历背包,内层for循环遍历物品。
本题求得是最小个数,既不是排列,也不是组合,所以先遍历哪一个都是可以的。
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-coins[i]]+1, dp[j]);}}}if(dp[amount] == INT_MAX) return -1;return dp[amount];}
};
第三题、完全平方数 力扣题目链接
也可以看作是完全背包问题,n是背包,然后j*j当做物品,用j*j去装n,求最小的个数
class Solution {
public:int numSquares(int n) {vector<int> dp(n+1, INT_MAX);dp[0] = 0;for(int i=0; i <= n; i++){for(int j=1;j*j <=i; j++){dp[i] = min(dp[i - j*j]+1, dp[i]);}}return dp[n];}
};