代码随想录刷题Day45 | 70.爬楼梯(进阶版)、322.零钱兑换、279. 完全平方数

今日任务

70. 爬楼梯(用动态规划解决)

322. 零钱兑换

279. 完全平方数

70.爬楼梯

主要思想

  • 使用多重背包思路做
  • 假设题目修改为每次爬1…m阶楼梯
  • 这里的1…m就是物品的质量
  • n就是背包的容量
  • dp[j] 表示的是组合总数,求排列数,多重背包
class Solution {
public:
// 使用背包思路做
// 假设题目修改为每次爬1...m阶楼梯
// 这里的1...m就是物品的质量
// n就是背包的容量
// dp[j] 表示的是组合总数,顺序有区别
// 多重背包
    int climbStairs(int n) {
        vector<int> dp(n + 1, 0);
        dp[0] = 1;
        int m = 2;
        // 先遍历背包,再遍历物品
        for (int j = 1; j <= n; ++j) {
            for (int i = 1; i <= m; ++i) {
                if (j >= i) dp[j] += dp[j - i];
            }
        }
        return dp[n];
    }
};

322.零钱兑换

主要思想

  • dp[j]:凑足总额为j所需钱币的最少个数为dp[j]

  • 确定递推

    • 凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i])
    • 所以dp[j] 要取所有 dp[j - coins[i]] + 1 中最小的
    • 递推公式:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);
  • dp数组如何初始化

    • 首先凑足总金额为0所需钱币的个数一定是0,那么dp[0] = 0;
    • 考虑到递推公式的特性,dp[j]必须初始化为一个最大的数(INT_MAX),否则就会在min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖。
class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> dp(amount + 1, INT_MAX); // 因为要取最小,所以都初始化为INT_MAX
        dp[0] = 0; // 但是当可以凑整时,还是从0开始算起,非0元素都应该初始化为INT_MAX
        for (int i = 0; i < coins.size(); ++i) {
            for (int j = coins[i]; j <= amount; ++j) {
                // 如果是初始值则直接跳过,因为无法凑整,且INT_MAX最后可能溢出
                if (dp[j - coins[i]] != INT_MAX) dp[j] = min(dp[j], dp[j - coins[i]] + 1);
            }
        }
        if (dp[amount] == INT_MAX) return -1;
        return dp[amount];
    }
};

279. 完全平方数

主要思想

  • dp数组定义 : dp[j] 表示和为j的最少完全平方数数量
  • 递推:dp[j] = min(dp[j - i * i] + 1, dp[j])
  • 初始化:dp[0] = 0, dp[1..j] = INT_MAX
class Solution {
public:
// dp[j] 表示和为j的最少完全平方数数量
// dp[j] = min(dp[j - i * i] + 1, dp[j])
// 初始化:dp[0] = 0, dp[1..j] = INT_MAX
    int numSquares(int n) {
        vector<int> dp(n + 1, INT_MAX);
        dp[0] = 0;
        for (int i = 1; i * i <= n; ++i) {
            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];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值