代码随想录训练营第四十五天|70.爬楼梯、322.零钱兑换、279.完全平方数

文章讲述了使用动态规划解决三个问题:70.爬楼梯,通过动态规划数组dp[i]表示爬到第i阶楼梯的方法数;322.零钱兑换,求解凑成特定金额所需的最少硬币数;279.完全平方数,找到和为给定数的完全平方数的最小数量。每个问题都涉及完全背包的概念,并通过迭代优化解法。
摘要由CSDN通过智能技术生成

70.爬楼梯

链接:LeetCode70.爬楼梯
首先回顾一下动态规划的解法

class Solution {
public:
    int climbStairs(int n) {
        if(n<=1) return 1;
        vector<int> dp(n+1,1);
        for(int i=2;i<=n;++i){
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[n];
    }
};

把本题抽象成完全背包问题。
背包体积为n,物品重量为1或者2,物品价值为1.

  1. 确定dp数组以及下标含义。dp[j]表示爬j阶楼梯到达楼顶的方法个数。
  2. 确定递推公式公式。dp[j] += dp[j-nums[i]].
  3. 数组初始化。dp[0]=1;
  4. 确定遍历顺序。由于求的是排列的个数。故先遍历背包后遍历物品。
  5. 举例推导dp数组。
class Solution {
public:
    int climbStairs(int n) {
        vector<int> dp(n+1,0);
        dp[0] = 1;
        vector<int>nums{1,2};
        for(int j=0;j<=n;++j){
            for(int i=0;i<2;++i){
                if(j>=nums[i]) dp[j] += dp[j-nums[i]];
            }
        }
        return dp[n];
    }
};

322.零钱兑换

链接:LeetCode322.零钱兑换
本题可以抽象为完全背包。
背包的体积为amount,物品的重量为coins[i],物品的价值为1.

  1. 确定dp数组以及下标含义。dp[j]表示凑成金额i所需的最少的硬币个数。
  2. 确定递推公式公式。dp[j] = min(dp[j],dp[j-coins[i]]+1).
  3. 数组初始化。由于求的是最小值,故将dp[j]都初始化为INT_MAX,但是由于要进行求和的操作,故将dp[0]初始化为0
  4. 确定遍历顺序。先遍历背包后遍历物品,或者先遍历物品后遍历背包都是可以的。
  5. 举例推导dp数组。
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) continue;
                dp[j]=min(dp[j],dp[j-coins[i]]+1);
            }
        }
        if(dp[amount]==INT_MAX) return -1;
        return dp[amount];
    }
};

279.完全平方数

链接:LeetCode279.完全平方数
本题可以抽象为完全背包问题:
首先找出小于等于n的完全平方数nums。背包的体积为n,物品的重量为nums[i],价值为1.

  1. 确定dp数组以及下标含义。dp[j]表示和为i的完全平方数的最少数量。
  2. 确定递推公式公式。dp[j] = min(dp[j],dp[j-i]+1)其中i为小于等于n的完全平方数
  3. 数组初始化。由于求的是最小值,故将dp[j]都初始化为INT_MAX,但是由于要进行求和的操作,故将dp[0]初始化为0
  4. 确定遍历顺序。先遍历背包后遍历物品,或者先遍历物品后遍历背包都是可以的。
  5. 举例推导dp数组。
class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n+1,INT_MAX);
        dp[0]=0;
        for(int i=1;i<=n;++i){
            int m = sqrt(i);
            if((m*m)!=i) continue;
            for(int j=i;j<=n;++j){
                dp[j] = min(dp[j],dp[j-i]+1);
                //这里是j-i而不是j-m,i才是完全平方数而不是m
            }
        }
        return dp[n];
    }
};

对完全平方数的判断进行改进

class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n+1,INT_MAX);
        dp[0]=0;
        //i*i一定是完全平方数
        for(int i=1;i*i<=n;++i){
            for(int j=i*i;j<=n;++j){
            	if(dp[j-i*i]==INT_MAX) continue;//防止溢出
                dp[j] = min(dp[j],dp[j-i*i]+1);
            }
        }
        return dp[n];

    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值