代码随想录算法训练营29期Day50|LeetCode 70,322,279

  文档讲解:爬楼梯(进阶)  零钱兑换  完全平方数

70.爬楼梯(进阶)

题目链接:https://kamacoder.com/problempage.php?pid=1067

思路:

       这其实是一个完全背包问题。1阶,2阶,.... m阶就是物品,楼顶就是背包。每一阶可以重复使用,例如跳了1阶,还可以继续跳1阶。问跳到楼顶有几种方法其实就是问装满背包有几种方法。

       设dp[i]:爬到有i个台阶的楼顶,有dp[i]种方法

       本题呢,dp[i]有几种来源,dp[i - 1],dp[i - 2],dp[i - 3] 等等,即:dp[i - j]

       那么递推公式为:dp[i] += dp[i - j]

       dp[0] 一定为1,dp[0]是递归中一切数值的基础所在,如果dp[0]是0的话,其他数值都是0了。

       下标非0的dp[i]初始化为0,因为dp[i]是靠dp[i-j]累计上来的,dp[i]本身为0这样才不会影响结果

核心代码:

include 
#include 
using namespace std;
int main() {
    int n, m;
    while (cin >> n >> m) {
        vector 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];
            }
        }
        cout << dp[n] << endl;
    }
}

322.零钱兑换

题目链接:https://leetcode.cn/problems/coin-change/description/

思路:

       题目中说每种硬币的数量是无限的,可以看出是典型的完全背包问题。

       设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]);

       首先凑足总金额为0所需钱币的个数一定是0,那么dp[0] = 0;

       考虑到递推公式的特性,dp[j]必须初始化为一个最大的数,否则就会在min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖。

       所以下标非0的元素都是应该是最大值。

核心代码:

class Solution {
public:
    int coinChange(vector& coins, int amount) {
        vector 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 - coins[j]] + 1, dp[i]);
                }
            }
        }
        if (dp[amount] == INT_MAX) return -1;
        return dp[amount];
    }
};

279.完全平方数

题目链接:https://leetcode.cn/problems/perfect-squares/description/

思路:

       完全平方数就是物品(可以无限件使用),凑个正整数n就是背包,问凑满这个背包最少有多少物品?

       设dp[j]:和为j的完全平方数的最少数量为dp[j]

       dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以凑成dp[j]。

       此时我们要选择最小的dp[j],所以递推公式:dp[j] = min(dp[j - i * i] + 1, dp[j]);

       dp[0]表示 和为0的完全平方数的最小数量,那么dp[0]一定是0。

       非0下标的dp[j]应该是多少呢?

       从递归公式dp[j] = min(dp[j - i * i] + 1, dp[j]);中可以看出每次dp[j]都要选最小的,所以非0下标的dp[j]一定要初始为最大值,这样dp[j]在递推的时候才不会被初始值覆盖

核心代码:

class Solution {
public:
    int numSquares(int n) {
        vector dp(n + 1, INT_MAX);
        dp[0] = 0;
        for (int i = 1; i * i <= n; i++) { // 遍历物品
            for (int j = i * i; j <= n; j++) { // 遍历背包
                dp[j] = min(dp[j - i * i] + 1, dp[j]);
            }
        }
        return dp[n];
    }
};

今日总结

        今日学习时长2h,接着八股文。

        找论文idea,头大。

你可能感兴趣的:(代码随想录算法训练营29期,算法,leetcode,职场和发展,c++,动态规划)