💖作者:小树苗渴望变成参天大树
🎉作者宣言:认真写好每一篇博客
🎊作者gitee:gitee
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!
文章目录
- 前言
前言
各位友友们,大概又快一个月没有更新新的文章了,前段时间再准备学校的期末考试,所以耽误了更文的速度,暑假我会一直持续的更新好的文章,从这篇开始我就开始更新关于动态规划算法的博客,一题一篇,让大家可以更好的学习的每一个题目,之前的C++和Linux也会同步更新,大家可以通过作者的专栏来进行模块化学习,话不多说,我们开始进入正文
我们先来看看第一题,这是一个比较简单的题目,也是最能体现我们动态规划解题思路的一个题目,我将通过这个题目给大家入门动态规划。
1137.第N个斐波那契数
这个题目我们先将它的表达式换成我们常见的
那什么是动态规划?
毕竟是第一次接触这个东西,博主先用感性的话术给大家讲解一下,理性的去讲,大家可能都听不懂,使用动态规划需要五个步骤
-
状态表示
是什么:就是又一个和数组一样的dp表,dp表里面的数据就表示一个状态,其实就是和数组一样
怎么来:
(1)题目要求(上面的题目就可以根据题目要求要求来将状态表示写出来,dp[n]就是第n个泰波那契数)
(2)经验(要多刷题)+题目要求(可以解决80%左右的题目)
(3)分析题目要求,发现重复子问题 -
状态转移方程
就是状态之间的关系方程,此题的状态转移方程就是这个
-
初始化
保证数组不越界,此题,我们只能从下标为3的开始进行往后面开始进行算,不然就会出现dp[-3],dp[-2],dp[-1],会越界 -
填表顺序
为了填写的当前的状态的时候,所需的状态已经计算过了,此题,非常的贴心,我们要的就是前三个泰波那契数T0=0,T1=T2=1,按照顺序进行填写就可以了 -
返回值
根据题目要求来确定返回值,此题,我们已经分析的状态表示里面的内容就是我们想要的返回值,所以返回值就是dp[n]
代码实现:
class Solution {
public:
int tribonacci(int n) {
int i=0;
if(n==0)return 0;
if(n==1||n==2)return 1;
int* dp=new int[n+1];//创建一个dp表
dp[0]=0;dp[1]=dp[2]=1;//填表顺序
for(int i=3;i<=n;i++)//初始化
{
dp[i]=dp[i-3]+dp[i-2]+dp[i-1];//状态转移方程
}
return dp[n];//返回值
}
};
动态规划的题目主要在前面的分析,代码很容易实现的,这个代码的时间复杂度O(n)和空间复杂度O(n).
动态规划还有一个点,就是空间优化,后面的题目大约又三四十道题目都不会又空间优化,毕竟是第一题入门,要把动态规划涉及的知识点都要讲解清楚,我们动态规划是创建一个数组,既然是数组空间复杂度就大概可能是O(n),我们怎么解决这个问题呢??使用滚动数组,我们来看图解:
我们发现求第五个泰波那契数和第一个泰波那契数没有关系,依次类推。用动态规划的话术说,就是求后面的状态和前面的状态的没有关系,就可以使用滚动数组来进行空间优化
滚动数组的代码优化:
class Solution {
public:
int tribonacci(int n) {
int i=0;
if(n==0)return 0;
if(n==1||n==2)return 1;
int a=0;int b=1,c=1;int d=0;
for(int i=3;i<=n;i++)//初始化
{
d=a+b+c;
a=b;b=c;c=d;
//d=c;c=b;b=a;//这样是错误的
}
return d;//返回值
}
};
运行结果:
到这里我们动态规划的第一题就讲解道这里,后面的每一题,我都将会通过这个方法来给大家讲解动态规划的五个步骤,让大家更好的理解动态规划,那我们下篇在见