动态规划:从入门到入土系列(一)

简介: 动态规划:从入门到入土系列(一)

前言

本篇是动态规划系列的入门基础题,以"第 n 个泰波那契数"和 "三步问题"为例子.

一、第 n 个泰波那契数

题目来源于:力扣

题目链接:传送门

题目描述:

泰波那契序列 Tn 定义如下:

T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2给你整数 n,请返回第 n 个泰波那契数 Tn 的值。

示例 1:

输入:n = 4
输出:4
解释:
T_3 = 0 + 1 + 1 = 2
T_4 = 1 + 1 + 2 = 4

示例2:

输入:n = 25
输出:1389537

算法讲解:

1.创建dp表.

确定状态表示:用dp[n]表示第 n 个泰波那契数 Tn 的值.

我们要返回Tn的值,也就是第n个泰波那契数,由于T0的存在(即有第0个泰波那契数),所以我们创建dp表的时候,需要创建n+1个大小的数组,即dp[n+1].

·需要设置的文字

2.初始化.

前面三个泰波那契数的值题目都已经给出,dp[0]=0,dp[1]=1,dp[2]=1;

3.填写dp表.

根据题目介绍,我们不难得出状态转移方程是:Tn+3 = Tn + Tn+1 + Tn+2

即:Tn = Tn-3 + Tn-2 + Tn-1

17e91dc9e9354bd291d1d5410a3915f5.png

本题中是直接给出了状态转移方程,大多数动态规划的题目是需要我们自己推导的.

4.确认返回值.

题目要求返回第 n 个泰波那契数 Tn 的值,那dp[n]不就是我们需要返回的吗?


5.细节处理:

由于0<n<=2时,无法进行完整的初始化操作,我们可以提前进行判定直接返回.

代码实现:

class Solution {
public:
    int tribonacci(int n) {
        //防止因为n过小导致的初始化问题
        if(n==0) return 0;
        if(n==1||n==2)return 1;
        //1.创建dp表
        int dp[n+1];
        //2.初始化
        dp[0]=0,dp[1]=1,dp[2]=1;
        //3.填表
        for(int i=3;i<=n;i++)
        {
            dp[i]=dp[i-3]+dp[i-2]+dp[i-1];
        }
        //4.确认返回值
        return dp[n];
    }
};

空间优化:

在上面的算法中,我们创建了n+1个大小的数组空间,所以空间复杂度是O(n),我们可以采用滚动数组的方法,将时间复杂度降到O(1).

其实我们可以不用创建n+1个大小的数组空间,因为只需要知道第n项的前三个,就可以推导出第四项,所以我们可以创建只有四个大小的数组空间.

dd337b5d5b06476cad43ea5791b7a45f.png

class Solution {
public:
    int tribonacci(int n) {
        //防止因为n过小导致的初始化问题
        if(n==0) return 0;
        if(n==1||n==2)return 1;
        //1.创建dp表
        int dp[4];
        //2.初始化
        dp[0]=0,dp[1]=1,dp[2]=1;
        //3.填表
        for(int i=3;i<=n;i++)
        {
            dp[3]=dp[2]+dp[1]+dp[0];
            //动态更新数组(滚动数组)
            dp[0]=dp[1];
            dp[1]=dp[2];
            dp[2]=dp[3];
        }
        //4.确认返回值
        return dp[3];
    }
};

3b92781d34e94cb191e2f4ae85ffcb83.png

二、三步问题

题目来源于:力扣

题目链接:传送门

题目描述:

三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。

示例1:

输入:n = 3
输出:4
说明: 有四种走法

示例2:

输入:n = 5
输出:13

算法讲解:

1.创建dp表:

确定状态表示:dp[n]代表有n阶楼梯时,小孩可以选择上楼的方式.

我们要j计算的是当有n阶台阶时,小孩有多少种上楼梯的方式.

并且此题规定:0个台阶时,有一种上楼方式.

所以我们创建dp表的时候,需要创建n+1个大小的数组,即dp[n+1].

2.初始化:

上楼梯的方法:dp[0]=1,dp[1]=1,dp[2]=2;

3.填写dp表.

先看懂题目意思,此题需要自行推导状态转移方程.

分析: dp[0]=1,dp[1]=1.

850e2642bac34c3d9b78931ff21befd0.png

4. 确认返回值:

dp[n]代表有n阶楼梯时,我们可以选择的上楼方式.所以返回dp[n]即可.

5.细节处理:

(1)由于0<n<=2时,无法进行完整的初始化操作,我们可以提前进行判定直接返回.

(2)由于这里数据比较大,所以每次进行"+"运算时,需要进行对结果取模(1000000007).

代码实现:

class Solution {
public:
    int waysToStep(int n) {
        const int MOD =1000000007;
        //防止因为n过小导致的初始化问题
        if(n==0||n==1)return 1;
        if(n==2)return 2;
    //创建dp数组
        int dp[n+1];
        //初始化操作
        dp[0]=1,dp[1]=1,dp[2]=2;
        //填表
        for(int i=3;i<=n;i++)
        {
            dp[i]=((dp[i-3]+dp[i-2])%MOD+dp[i-1])%MOD;//这里一定要记得取模
        }
        //返回值
        return dp[n];
    }
};

运行结果:

578e9cb9b10e4fe9a1aa52d48e96a609.png

当然也可以使用滚动数组的方式进行空间优化,这里就不再演示了.

三、 结语:

本篇是动态规划系列的入门基础题,题目难度偏简单,后续会慢慢更新,难度有所提升.

下篇见!

目录
相关文章
|
Ubuntu 应用服务中间件 nginx
docker入门-快速学会docker
本文介绍了Docker的基本概念,包括镜像、容器、tar文件、Dockerfile和仓库,并通过实际操作演示了如何使用Docker。从拉取Nginx镜像、运行容器、修改容器内容、保存容器为新镜像,到使用Dockerfile构建自定义镜像,最后讲解了如何保存和恢复镜像。文中还推荐了一个在线实践平台Play with Docker,方便读者快速上手Docker。
979 5
docker入门-快速学会docker
CSS3 flex 布局在 wrap 换行模式下,让中间指定元素换行
CSS3 flex 布局在 wrap 换行模式下,让中间指定元素换行
1598 0
|
关系型数据库 MySQL 数据库
探究数据库开源协议:PostgreSQL vs MySQL
探究数据库开源协议:PostgreSQL vs MySQL
|
存储 开发工具 数据安全/隐私保护
什么是Iaas,Paas,Saas?
IaaS(基础设施即服务)提供网络上的IT基础设施服务,按需计费;PaaS(平台即服务)则提供运算平台与解决方案服务,助力用户在云端基础设施上构建与部署应用;而SaaS(软件即服务)通过网络交付软件服务,让用户能够便捷地使用已部署好的应用程序,无需关心底层技术细节。以厨房为例,IaaS如同提供厨房用品,用户自行烹饪;PaaS则是提供预制菜,减少前期准备;SaaS则像点外卖,直接享用成品菜肴。
5718 3
C语言每日一练——Day01:求最大公约数(三种方法)
C语言每日一练——Day01:求最大公约数(三种方法)
|
JavaScript 前端开发 算法
vue3、react组件数据传值对比分析——父组件传递子组件,子组件传递父组件(一)
vue3、react组件数据传值对比分析——父组件传递子组件,子组件传递父组件
279 0
|
缓存 Java 数据库连接
一文彻底搞懂Mybatis系列(十)之SqlSession、SqlSessionFactory和SqlSessionFactoryBuilder详解
一文彻底搞懂Mybatis系列(十)之SqlSession、SqlSessionFactory和SqlSessionFactoryBuilder详解
1469 1
|
缓存
如何彻底卸载VSCode及其原来的插件配置缓存
如何彻底卸载VSCode及其原来的插件配置缓存
1709 0
|
运维 Cloud Native 持续交付
构建未来:云原生架构的演变与实践
【5月更文挑战第17天】 在数字化转型的浪潮中,企业正迅速采用云原生技术来构建和部署应用程序。本文将深入探讨云原生架构的核心概念、发展历程以及如何在现代IT环境中实现敏捷、可扩展和高效的服务。通过对容器化、微服务、持续集成和持续部署(CI/CD)等关键技术的分析,我们将揭示如何利用云原生方法论来优化资源利用、加快产品上市速度,并提高系统的可靠性。
167 3
|
机器学习/深度学习 算法
m基于深度学习的32QAM调制解调系统相位检测和补偿算法matlab仿真
m基于深度学习的32QAM调制解调系统相位检测和补偿算法matlab仿真
318 1