代码随想录训练营Day38 动态规划part01 509. 斐波那契数 ● 70. 爬楼梯 ● 746. 使用最小花费爬楼梯

509. 斐波那契数

题目链接:509. 斐波那契数 - 力扣(LeetCode)

文章链接:代码随想录 (programmercarl.com)

视频链接: 手把手带你入门动态规划 | leetcode:509.斐波那契数

接下来,我将初识动态规划,这道题是动态规划中的简单题。

首先,什么是动态规划?

动态规划中每一个状态一定是由上一个状态推导出来的 。就比如这道题,我想求F(3)就要知道F(2)和F(1),想知道F(2)又要知道F(1)和F(0)。我们通过遍历,逐层状态推导到当前状态的过程,就是动态规划。

用 动态规划五部曲解决该问题:

(1)确定dp数组和下标的含义。

这道题我们需要用dp数组来储存每一层状态产生的值,dp[i]就代表了下标i的斐波那契数列的值,也就是i+1个斐波那契数列的值。

vector<int> dp(n+1)

(2)确认递推公式。

这道题简单就在于题目已经给出了递归公式。

dp[i]=dp[i-1]+dp[i-2]

(3)dp数组初始化。

所有状态产生的值都是由第一层状态的初始值而产生的,所以需要对第一层状态的值初始化。

而斐波那契数列中,第一层状态是dp[0]和dp[1]。

dp[0]=0;//dp数组初始化
dp[1]=1;

(4)确定遍历顺序。

我们想知道某一层状态产生的值,就一定要知道它的前个状态产生的值,想知道dp[i]就要知道dp[i-1]和dp[i-2],所以这道题肯定是从前往后遍历。

for(int i=2;i<=n;i++)

(5)举例推导dp数组

就是举例子带进我推导出的递推数组中,看看是否符合。

总代码如下:

class Solution {
public:
    int fib(int n) {
        if(n<=1) return n;
        vector<int> dp(n+1);//确认dp数组以及下标的含义
        dp[0]=0;//dp数组初始化
        dp[1]=1;
        for(int i=2;i<=n;i++)//确认递归顺序
        {
            dp[i]=dp[i-1]+dp[i-2];//确认递归公式
        }
        return dp[n];
    }
};

● 70. 爬楼梯 

 题目链接:70. 爬楼梯 - 力扣(LeetCode)

文章链接:代码随想录 (programmercarl.com)

视频链接: 带你学透动态规划-爬楼梯|LeetCode:70.爬楼梯)

 这道题,依旧可以用动态规划解决。

动规五部曲:

(1)确定dp数组以及下标的含义

这边的dp数组是用来记录爬n阶楼梯的方法个数,dp[i]代表爬第i阶楼梯的方法个数。

vector<int> dp(n+1)

(2)确定递推公式。

我一开始想的是,由于我一步可以走一阶或者两阶,所以如果想知道i阶楼梯的方法个数dp[i],就需要知道dp[i-1]和dp[i-2],dp[i-2]想到dp[i],可以走两步1阶,也可以一步2阶,所以我就误推成

dp[i]=dp[i-1]+dp[i-2]*2

但是检验时发生了错误,后来又想了想,发现了问题。

我想的“dp[i-2]想到dp[i],可以走两步1阶,也可以一步2阶”,但如果在i-2阶先走一步1阶,就到了i-1阶,所以我想的这种情况其实包含在了dp[i-1]中。

正确递推公式为:

dp[i]=dp[i-1]+dp[i-2];

(3)dp数组初始化。

想知道i阶楼梯的方法个数dp[i],就需要知道dp[i-1]和dp[i-2],dp[i-2],所以我们需要最初始的状态,dp[1]和dp[2].

dp[1]=1;
dp[2]=2;

(4)确认遍历顺序。

肯定是从前往后遍历,常识了......

(5)举例推导dp数组

这道题其实就是斐波那契数列套了个外壳

 总代码如下:

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

746. 使用最小花费爬楼梯 

 题目链接:746. 使用最小花费爬楼梯 - 力扣(LeetCode)

文章链接:代码随想录 (programmercarl.com)

视频链接: 动态规划开更了!| LeetCode:746. 使用最小花费爬楼梯

动态五部曲 

(1)确定dp数组和下标含义

我们用dp数组来记录到每一层台阶的花费,那么dp[i]就是爬到第i层台阶需要的花费。

 vector<int> dp(n+1);

(2)确定递推公式

想到第i层有两种方法,从第i-2层直接跨2阶或者从第i-1层跨1阶,由于我们需要求最低花费,所以我们应该找两者中花费少的那个。

dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);

(3)dp数组初始化

题目中说了

你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。

这就意味着第0阶和第1阶都可以是我的初识点,当然不需要花费

dp[0]=0;
dp[1]=0;

(4)确认遍历顺序

也很明显,爬楼梯的题一般都是从前往后遍历。

(5)举例推导dp数组

总代码如下:

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        int n=cost.size();
        vector<int> dp(n+1);
        dp[0]=0;
        dp[1]=0;
        for(int i=2;i<n;i++)
        {
            dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
        }
        return min(dp[n-1]+cost[n-1],dp[n-2]+cost[n-2]);
    }
};

 

Day38打卡成功,初识动态规划,我发现动态规划只要按照动规五部曲,思路还是很清晰的,递推的思路是关键点。再接再厉吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值