首页 > 其他分享 >【LeetCode动态规划#01】动规入门:求斐波那契数 + 爬楼梯(熟悉解题方法论)

【LeetCode动态规划#01】动规入门:求斐波那契数 + 爬楼梯(熟悉解题方法论)

时间:2023-03-24 13:36:44浏览次数:53  
标签:契数 01 初始化 递推 求斐波 数组 楼梯 方法 dp

斐波那契数

力扣题目链接(opens new window)

斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) = 0,F(1) = 1 F(n) = F(n - 1) + F(n - 2),其中 n > 1 给你n ,请计算 F(n) 。

示例 1:

  • 输入:2
  • 输出:1
  • 解释:F(2) = F(1) + F(0) = 1 + 0 = 1

示例 2:

  • 输入:3
  • 输出:2
  • 解释:F(3) = F(2) + F(1) = 1 + 1 = 2

示例 3:

  • 输入:4
  • 输出:3
  • 解释:F(4) = F(3) + F(2) = 2 + 1 = 3

提示:

  • 0 <= n <= 30

思路

本来这题应该是用递归写的,但作为DP的入门题也合适

先说明一下,DP五部曲:

  • 确定DP数组以及数组的下标定义
  • 确定递推公式
  • 确定DP数组如何初始化
  • 确定遍历顺序
  • 打印DP数组(主要用于debug)
五部曲分析

那下面就用这题来做一个示范

1、确定DP数组以及数组的下标定义

做动规题都需要先明确dp数组dp[i]的定义

在本题中,dp[i]应该指的是:第i个斐波那契数的数值是dp[i]

2、确定递推公式

因为刚刚入门,就目前我的理解,所谓的递推公式就是题目中的某种解决问题的思路的抽象形式

像这里,题目直接就给了F(n) = F(n - 1) + F(n - 2)

这个公式就是用来求斐波那契数的,那么这个公式也就是要找的递推公式(直接给出了所以本题简单)

结合本题dp[i]的定义可以得到最终需要的递推公式:dp[i] = dp[i - 1] + dp[i - 2]

3、确定DP数组初始化方式

题目也给了:F(0) = 0,F(1) = 1,所以初始化方式如下:

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

4、确定遍历顺序

因为dp[i] = dp[i - 1] + dp[i - 2],先有的dp[i - 1]和dp[i - 2]才能求dp[i]

故遍历顺序应该是从前向后

5、打印DP数组

这一步的意思就是,根据我们推断的递推公式,将dp[i]的值自行计算出来看看对不对

代码

class Solution {
public:
    int fib(int n) {
        if(n <= 1) return n;//如果n小于等于1,即直接得到第1个斐波那契数(0 + 1),因此直接返回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];//返回dp数组中n处的值,即第n个斐波那契数
    }
};

爬梯子

力扣题目链接(opens new window)

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

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

注意:给定 n 是一个正整数。

示例 1:

  • 输入: 2
  • 输出: 2
  • 解释: 有两种方法可以爬到楼顶。
    • 1 阶 + 1 阶
    • 2 阶

示例 2:

  • 输入: 3
  • 输出: 3
  • 解释: 有三种方法可以爬到楼顶。
    • 1 阶 + 1 阶 + 1 阶
    • 1 阶 + 2 阶
    • 2 阶 + 1 阶

思路

先看看题目描述,要求的是爬到楼顶有多少种方法

再看一下示例2,

爬到第一层楼梯有1种方法;

爬到第二层楼梯有2种方法;(一阶一阶爬、一次爬两阶)

那么爬到第三层楼梯就有3种方法;(一阶一阶爬、一阶+二阶、二阶+一阶)

实际上到第三层楼梯的方法数可以通过到第一层和到第二层的方法数推出

那么就可以用dp

五部曲

还是五步走

1、确定dp数组的含义

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

2、确定递推公式

如何推出递推公式?要结合对于dp[i]的定义

1阶   1种  dp[i-2],上i-2层楼梯,有dp[i - 2]种方法(现在是i-2阶,再往上走1阶到i-1阶)
2阶   2种  dp[i-1],上i-1层楼梯,有dp[i - 1]种方法(现在是i-1阶,再往上走1阶到i阶)
3阶   3种  dp[i],上i层楼梯,有dp[i]种方法

好,到第i层楼梯(也就是第3层),按dp数组定义来是有dp[i]种方法

现在往回看,在i-2层时,我们可以选择一次爬两阶,然后上到第i层;同理在i-1层时,我们也可以选择一次爬一阶,然后上到第i层;

这说明,到达第i层楼梯的dp[i]种方法中包含着爬上i-2层和i-1层时的方法

由此可以总结出到达第i层楼梯的递推公式:dp[i] = dp[i - 2] + dp[i - 1]

3、确定dp数组的初始化方式

之前在 斐波那契数 中,我们讨论初始化时,是有对dp[0]进行初始化的

但是这里可以不用讨论dp[0],下面来说具体原因

在确定dp数组的初始化方式时,我们仍然要遵循第一步中给dp数组下的定义,即dp[i]:爬到第i层楼梯有dp[i]种方法

根据此定义来解释dp[0]就有点问题,爬到第0层楼有dp[0]种方法?

都0层楼了,相当于不用走直接在终点了,这样就可能会有多种解释

最好的办法就是不讨论dp[0]的情况,而且题目中说了n是一个正整数,根本就没说n有为0的情况。

那么根据dp数组的定义,我们可以得到以下初始化:

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

显然这是无争议,也是符合dp数组定义的

4、确定遍历顺序

分析到这里了,你肯定发现这题和斐波那契数其实是一样的

第i个数(阶梯)需要依靠第i-1和i-2个数(阶梯)确定

自然的,本题的遍历顺序也需要是从前向后

代码

因为我们不讨论dp[0],所以应该从dp[3]开始累加

步骤:

1、处理n小于等于1的情况

2、创建dp数组,并初始化

3、按照设定的顺序开始遍历累加dp数组,最后返回dp[n]

class Solution {
public:
    int climbStairs(int n) {
        if(n <= 1) return n;//如果n小于等于1,那么只有一种爬楼梯的方法,即直接到达目标楼层,因此直接返回n即可。
        vector<int> dp(n + 1);//创建dp数组

        dp[1] = 1;//初始化dp数组
        dp[2] = 2;
        for(int i = 3; i <= n; ++i){// 注意i是从3开始的
            dp[i] = dp[i - 2] + dp[i - 1];
        }
        return dp[n];//返回dp数组中n处的值,即爬到第i层楼梯有dp[i]种方法
    }
};

在这段代码中,如果n小于等于1,那么只有一种爬楼梯的方法,即直接到达目标楼层,因此直接返回n即可。

如果n大于1,那么创建一个大小为n+1的dp数组来记录每个楼梯台阶的爬楼梯方法数。然后初始化dp数组的前两个元素为1和2,因为到达第一层楼梯只有一种方法,到达第二层楼梯有两种方法。接着通过循环,从第三个元素开始依次计算每个楼梯的爬楼梯方法数,即dp[i] = dp[i - 2] + dp[i - 1],最后返回dp数组中n处的值,即到达第n层楼梯的爬楼梯方法数。

标签:契数,01,初始化,递推,求斐波,数组,楼梯,方法,dp
From: https://www.cnblogs.com/DAYceng/p/17251244.html

相关文章

  • 2017双11交易系统TMF2.0技术揭秘,实现全链路管理
    摘要: 本文是《2017双11交易系统TMF2.0技术揭秘》演讲整理,主要讲解了基于TMF2.0框架改造的交易平台,通过业务管理域与运行域分离、业务与业务的隔离架构,大幅度提高了业务在可......
  • Games101-Cp2-Rasterization
    所谓光栅化就是在屏幕上画出对应该显示的像素值。采样(Sampling)光栅化最简单的方法就是采样,采样就是对连续函数离散化的过程。如:在屏幕空间中定义的三角形,采样过程就是......
  • bzoj 2006 [NOI2010] 超级钢琴 线段树求区间极值+优先队列
    挺神奇的一道题,唯一想不通的是为什么放在主席树的题单里..首先暴力找出所有的合法区间显然是不可能的。考虑怎么贪心,假如固定每个L作为左端点,那么合法的区间就是[L+l-1,L......
  • 2017-D
    2017-D数据库部分使用Windows身份验证登录SQLServer,建立数据库test0322,文件日志保存到一个专门的文件夹建表备份数据库,选定所创建数据库,右键-任务-备份-选择自己......
  • 2015-CS
    2015-CS数据库部分createtable[EMPLOYEE]( [EmpNo]varchar(10)notnullprimarykey, [EmpName]varchar(10)notnull, [EmpSex]varchar(5)check([EmpSex]='男......
  • 2018-D
    2018-D新建数据库test0317,目录为考试目录,并在完成建表后备份1、建表:use[test0317];createtable[STD_INFO]( [std_id]intnotnullprimarykey, [std_name]v......
  • 2017-A
    2017-A题目描述:输入一个字符串,要求输出能把所有的小写字符放前面,大写字符放中间,数字放后面,并且中间用空格隔开,如果同种类字符间有不同种类的字符,输出后也要用字符隔开。......
  • Correct a Posted Invoice with AX2012
    MicrosoftDynamicsAXemploysstrictcontrolsaroundthemodificationofpostedfinancialtransactions,buttherearetimeswhenwemakemistakesorvariables......
  • 设要采用CRC编码传送的数据信息x=1001,当生成多项式为G(x)=1101时,请写出它的循环校验码
    题目:设要采用CRC编码传送的数据信息x=1001,当生成多项式为G(x)=1101时,请写出它的循环校验码。若接收方收到的数据信息x'=1101,说明如何定位错误并纠正错误根据题目描述,需......
  • 后门原理与实践—20201229赵斌
    Exp2后门原理与实践—20201229赵斌基础问题回答例举你能想到的一个后门进入到你系统中的可能方式?在网上下载软件的时候,后门很有可能被捆绑在下载的软件当中;浏览网页......