算法训练营第三十八天||● 理论基础 ● 509. 斐波那契数 ● 70. 爬楼梯 ● 746. 使用最小花费爬楼梯

● 理论基础 

五步走:

确定dp数组

递推公式

dp数组初始化

遍历顺序

打印dp数组

 ● 509. 斐波那契数

这道题比较简单,但自己不看答案还做不出来,没想到用初始的方法

先看递归 只需要两行代码 确定终止条件 和逻辑

class Solution {
public:
    int fib(int n) {
        //递归
        if(n<2) return n;
        return fib(n-1)+fib(n-2);

    }
};

接下来看动态规划五部曲:

class Solution {
public:
    int fib(int n) {
        if(n == 0) return 0;
        if(n == 1) return 1;
        //初始化dp数组
        vector<int> dp(n+1);
        //dp数组初始化
        dp[0]=0;
        dp[1]=1;
        //遍历顺序从前向后
        for(int i = 2;i<=n;i++){
            //递推公式
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[n];

    }
};

● 70. 爬楼梯

这道题难点在递推公式 分析之后发现这道题和斐波那契数列的递推公式一摸一样

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

dp[i]: 爬到第i层楼梯,有dp[i]种方法

确定递推公式

如何可以推出dp[i]呢?

从dp[i]的定义可以看出,dp[i] 可以有两个方向推出来。

首先是dp[i - 1],上i-1层楼梯,有dp[i - 1]种方法,那么再一步跳一个台阶不就是dp[i]了么。

还有就是dp[i - 2],上i-2层楼梯,有dp[i - 2]种方法,那么再一步跳两个台阶不就是dp[i]了么。

那么dp[i]就是 dp[i - 1]与dp[i - 2]之和!

所以dp[i] = dp[i - 1] + dp[i - 2] 。

在推导dp[i]的时候,一定要时刻想着dp[i]的定义,否则容易跑偏。

这体现出确定dp数组以及下标的含义的重要性!

dp数组如何初始化

再回顾一下dp[i]的定义:爬到第i层楼梯,有dp[i]种方法。

那么i为0,dp[i]应该是多少呢,这个可以有很多解释,但基本都是直接奔着答案去解释的。

例如强行安慰自己爬到第0层,也有一种方法,什么都不做也就是一种方法即:dp[0] = 1,相当于直接站在楼顶。

但总有点牵强的成分。

那还这么理解呢:我就认为跑到第0层,方法就是0啊,一步只能走一个台阶或者两个台阶,然而楼层是0,直接站楼顶上了,就是不用方法,dp[0]就应该是0.

其实这么争论下去没有意义,大部分解释说dp[0]应该为1的理由其实是因为dp[0]=1的话在递推的过程中i从2开始遍历本题就能过,然后就往结果上靠去解释dp[0] = 1

从dp数组定义的角度上来说,dp[0] = 0 也能说得通。

需要注意的是:题目中说了n是一个正整数,题目根本就没说n有为0的情况。

所以本题其实就不应该讨论dp[0]的初始化!

我相信dp[1] = 1,dp[2] = 2,这个初始化大家应该都没有争议的。

所以我的原则是:不考虑dp[0]如何初始化,只初始化dp[1] = 1,dp[2] = 2,然后从i = 3开始递推,这样才符合dp[i]的定义。

确定遍历顺序

从递推公式dp[i] = dp[i - 1] + dp[i - 2];中可以看出,遍历顺序一定是从前向后遍历的

举例推导dp数组

举例当n为5的时候,dp table(dp数组)应该是这样的

70.爬楼梯

如果代码出问题了,就把dp table 打印出来,看看究竟是不是和自己推导的一样。

此时大家应该发现了,这不就是斐波那契数列么!

唯一的区别是,没有讨论dp[0]应该是什么,因为dp[0]在本题没有意义!

 

class Solution {
public:
    int climbStairs(int n) {
        if(n<2) 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. 使用最小花费爬楼梯 

还是五部曲

明确dp[i]含义 表示到达第i个台阶需要的最少花费

递推公式 与i-1和i-2有关系 还有他们的cost

初始化,到达第0个台阶和第一个台阶的最小花费为0

遍历顺序

打印dp数组

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值