代码随想录打卡第三十三天

代码随想录–动态规划部分

day 33 动态规划第一天



前言

代码随想录知识链接:代码随想录

动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。

所以动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的

而动态规划也有做法模板:
1、确定dp数组(dp table)以及下标的含义
2、确定递推公式
3、dp数组如何初始化
4、确定遍历顺序
5、举例推导dp数组

这就不同于贪心算法的灵光一现了,具体在题目中就可以慢慢理解


一、力扣509–斐波那契数

代码随想录题目链接:代码随想录

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。给定 n ,请计算 F(n)

确定动态数组dp,并且初始化dp(0) = 0, dp(1) = 1

确定递归方式:F(n) = F(n - 1) + F(n - 2)

正常写就好了

代码如下:

class Solution {
public:
    int fib(int n) {
        if(n <= 1) return n;
        vector<int> dp;
        dp.push_back(0);
        dp.push_back(1);
        for(int i = 2; i <= n; i ++)
        {
            int temp = dp[i-1] + dp[i-2];
            dp.push_back(temp);
        }
        return dp[dp.size() - 1]; 
    }
};

二、力扣70–爬楼梯

代码随想录题目链接:代码随想录

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

考虑如何能够建模成一个动态规划问题

动态数组用来记录第i层楼梯能够使用的方法数量

那么明显有:dp[i] = dp[i-1]+dp[i-2]的关系

因为从第i-1到第i层只有迈一步这一个选项,从i-2到i只有迈两步这一个选项

而同时i-2迈两次一步到达i层这个选择已经包含在dp[i -1]中了

那么初始化要怎么做呢,保证i-2不越界的话,i从2开始,则需要初始化dp[0]和dp[1]

但是压根没有0层这回事,所以实际上从1层开始,dp[1] = 1和dp[2] = 2

就可以写了

代码如下:

class Solution {
public:
    int climbStairs(int n) {
        if(n <= 2) return n;
        vector<int> dp;
        dp.push_back(0);
        dp.push_back(1);
        dp.push_back(2);
        for(int i = 3; i <= n; i ++)
        {
            int temp = dp[i-1] + dp[i-2];
            dp.push_back(temp);
        }
        return dp[dp.size() - 1];
    }
};

三、力扣746–使用最小花费爬楼梯

代码随想录题目链接:代码随想录

给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。

考虑如何构建动态规划问题,即dp数组要记录什么

要求最低花费,那么dp可以用于记录每层的最低消费

即dp[i]代表到达第i层的最低消费

而每次可以选择爬一层或者两层,则dp[i]应当由dp[i-1]和dp[i-2]来决定

实际上是从dp[i-1]+cost[i-1]dp[i-2] + cost[i-2]中选择一个最小的

那么更新公式就是dp[i] = min(dp[i-1]+cost[i-1], dp[i-2] + cost[i-2])

再考虑dp的初始化,包含i-2,所以i至少是2开始,需要初始化0和1的元素

而由于1和0是起始层,并不需要花费体力,cost[0]和cost[1]分别是说从0层出发和从1层出发需要花费的体力,所以dp[0] = dp[1] = 0

代码如下:

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        vector<int> dp;
        dp.push_back(0);
        dp.push_back(0);
        for(int i = 2; i <= cost.size(); i ++)
        {
            int temp = min(dp[i-1]+cost[i-1], dp[i-2] + cost[i-2]);
            dp.push_back(temp);
        }
        return dp[dp.size() - 1];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值