代码随想录Day45、46(01背包、完全背包刷题):Leetcode70、322、279、2915、139(动态规划)

刷的不是算法、是套路

Leetcode70:

问题描述:

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

代码及注释:

class Solution {
public:
    int dp[50];
    int climbStairs(int n) {
        dp[0]=1;

        //完全背包问题
        //求排列,先遍历背包,再遍历物品
        for(int i=1;i<=n;i++){
            for(int j=1;j<=2;j++){
                if(i<j)continue;
                //递推公式为 dp[i][j]=dp[i-1][j]+dp[i][j-w[i]];
                //转成滚动数组
                dp[i]+=dp[i-j];
            }
        }
        return dp[n];
    }
};

Leetcode322:

问题描述:

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

你可以认为每种硬币的数量是无限的。

代码及注释:

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {

        //完全背包问题,一定要看清题目,不然寄
        
        vector<int>dp(amount+1,10005);

        //根据二维递推公式 dp[i][j]=min(dp[i-1][j],dp[i][j-w[i]]+1)
        //dp[1][1]=min(dp[0][1],dp[0][0]+1)=1
        dp[0]=0;

        for(int i=0;i<coins.size();i++){
            //为什么从小到大遍历,因为当前层的后面的元素需要用的当前层前面计算的元素
            for(int j=coins[i];j<=amount;j++){
                dp[j]=min(dp[j],dp[j-coins[i]]+1);
            }
        }
        return dp[amount]==10005?-1:dp[amount];
    }
};

Leetcode279:

问题描述:

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,149 和 16 都是完全平方数,而 3 和 11 不是。

代码及注释:

class Solution {
public:
    int numSquares(int n) {
        //完全背包问题,我们做的不是算法,是套路
        vector<int>dp(n+1,10005);

        int ans[105]={0};
        //物品存储的是1-100的平方数
        for(int i=1;i<=100;i++){
            ans[i]=i*i;
        }

        dp[0]=0;
        //遍历物品
        for(int i=1;i<=100;i++){
            for(int j=ans[i];j<=n;j++){
                dp[j]=min(dp[j],dp[j-ans[i]]+1);
            }
        }
        return dp[n];
    }
};

Leetcode2915:

问题描述:

给你一个下标从 0 开始的整数数组 nums 和一个整数 target 。

返回和为 target 的 nums 子序列中,子序列 长度的最大值 。如果不存在和为 target 的子序列,返回 -1 。

子序列 指的是从原数组中删除一些或者不删除任何元素后,剩余元素保持原来的顺序构成的数组。

代码及注释:

class Solution {
public:
    int lengthOfLongestSubsequence(vector<int>& nums, int target) {
        //01 背包问题,我学的不是算法,是模板

        vector<int>dp(target+1,-1005);

        dp[0]=0;

        for(int i=0;i<nums.size();i++){
            for(int j=target;j>=nums[i];j--){
                dp[j]=max(dp[j],dp[j-nums[i]]+1);
            }
        }

        return max(-1,dp[target]);

    }
};

Leetcode139:

问题描述:

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true

注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

代码及注释:

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        //类似完全背包问题
        vector<bool>dp(s.size()+1,false);

        dp[0]=true;

        //dp[j]=dp[j]||dp[j-wordDict[i].size()] i[0,wordDict.size()]
        for(int j=1;j<=s.size();j++){
            for(int i=0;i<wordDict.size();i++){
                int len=wordDict[i].size();
                if(j>=len&&s.substr(j-len,len)==wordDict[i]){
                    dp[j]=dp[j]||dp[j-len];
                }
            }
        }
        return dp[s.size()];
    }
};

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值