算法王冠上的明珠——动态规划之斐波那契数列问题

目录

[1. 什么是动态规划](#1. 什么是动态规划)

[2. 动态规划步骤](#2. 动态规划步骤)

状态表示

状态转移方程

初始化

填表顺序

返回值

[3. 例题讲解及具体代码](#3. 例题讲解及具体代码)

[3.1 LeetCode1137. 第 N 个泰波那契数](#3.1 LeetCode1137. 第 N 个泰波那契数)


这篇文章是我第一篇关于动态规划的,所以我会先从什么是动态规划说起。

1. 什么是动态规划

动态规划是一种通过将复杂问题分解为重叠子问题,并利用子问题的解来高效求解原问题的算法思想。它的核心是避免重复计算,通过存储中间结果(即 "记忆化")来优化时间复杂度。

其实简单来说就是通过前面的状态来定义后面的状态,比如说我们前面关于前缀和的文章其实就可以被归为动态规划的一种,只不过它比较简单,所以我把它放在了基础算法里面。

2. 动态规划步骤

做动态规划类题目的步骤就是下面这几步。

状态表示

状态表示就是我们数组对应的那个位置的值的含义,简单来说就是那个值代表着什么。比如说我们前面说的前缀和,那他的状态表示就是代表着原数组前面这些数的累加。

状态转移方程

状态转移方程就是根据上面的状态表示来得到的一个公式,比如说我们前面说的前缀和,它的状态转移方程就是dp[i]=dp[i-1]+nums[i]。

初始化

初始化的作用简单来说就是为了防止数组越界访问,所以我们在一开始会给dp表的一小部分值提前给好。方便我们后续计算。拿前缀和来说就是第0个位子我们会直接给0。

填表顺序

之所以我们要有填表顺序,是因为我们填当前位置的值会使用到前面的一些值,那么我们要确保前面的这些值都已经计算好了。

返回值

返回值就是返回题目要求的那个值。

接下来我们通过几道例题来了解这几个步骤。

3. 例题讲解及具体代码

3.1 LeetCode1137. 第 N 个泰波那契数

接下来我们来讲解下面这道题,题目意思也很简单,就是当前位置的值是由前面三个位置的值得来的。

所以在这道题里面它的状态表示就是当前位置值等于前面三个位置的值的和。

所以在这道题里面它的状态转移方程就是dp[i]=dp[i-1]+dp[i-2]+dp[i-3]。

它的初始化就是第0个位子设置为0,第一个和第二个位置设置为1。

填表顺序就是从前往后就好。

返回值就是第n个位置的值。

我们看下面这个代码,其实我们做动态规划的题目,只要可以把上面的这五步给写出来,那么代码的实现也就变的很简单了。

cpp 复制代码
class Solution {
public:
    int tribonacci(int n) {
        if(n==0) return 0;
        if(n==1||n==2) return 1;
        vector<int> dp(n+1);
        dp[0]=0;
        dp[1]=1;
        dp[2]=1;
        for(int i=3;i<=n;++i)
            dp[i]=dp[i-1]+dp[i-2]+dp[i-3];
        return dp[n];
    }
};

3.2 面试题 08.01. 三步问题

我们看下面这道题就稍微有一点点难了,要我们算的是小孩走到这n步时的方法。

状态表示:dp[n]表示走到当前位置时的方法数。

状态转移方程:这道题的状态转移方程稍微有点难,我们看下面这个图,0代表的是地板。然后我们到a就1种办法(一步),到b有2种(一步一步,两步),到c的方法有4种(一步一步一步,一步两步,两步一步,三步),接着我们就不用自己算了,因为按照题目的要求,从a,b,c位置可以走到d位置,所以我们这里直接就是d前面三个位置办法的和就好了。我一开始在做的时候是想着是前三个位置的办法数加上多少多少,后来经过尝试发现不是。因为我们可以这样去想如果a位置的值要加上多少多少的话,那么就会把b和c的一部分给计算进去了,会造成重复计算,所以我们不要去关心abc是怎么到d位置的,我们要记住每一个位置的值代表的是到该位置的方法数,而一个位置只有它前面的三个可以到,所以加上前面三个的方法数就好了。

PS:如果还是觉得不太理解的话,那么就画个图,把abc的方法都画出来,这样也可以理解。

初始化:在上面已经写了,到a就1种办法(一步),到b有2种(一步一步,两步),到c的方法有4种(一步一步一步,一步两步,两步一步,三步)。

填表顺序:由题可得是从前向后填表。

返回值:返回值就是n位置的方法数。

我们看,只要我们知道上面的那5个,那么代码就可以直接写出来了。

我们在dp[i-1]+dp[i-2]这里也模上了一个1000000007,是因为在这里也会过大。所以我们要先模一下。

cpp 复制代码
class Solution {
public:
    int waysToStep(int n) {
        if(n==1) return 1;
        if(n==2) return 2;
        if(n==3) return 4;
        vector<int> dp(n+1);
        dp[1]=1;
        dp[2]=2;
        dp[3]=4;
        for(int i=4;i<=n;++i)
            dp[i]=((dp[i-1]+dp[i-2])%1000000007+dp[i-3])%1000000007;
        return dp[n];
    }
};
相关推荐
你撅嘴真丑3 小时前
第九章-数字三角形
算法
uesowys3 小时前
Apache Spark算法开发指导-One-vs-Rest classifier
人工智能·算法·spark
AI_56783 小时前
AWS EC2新手入门:6步带你从零启动实例
大数据·数据库·人工智能·机器学习·aws
ValhallaCoder3 小时前
hot100-二叉树I
数据结构·python·算法·二叉树
董董灿是个攻城狮3 小时前
AI 视觉连载1:像素
算法
CRzkHbaXTmHw4 小时前
探索Flyback反激式开关电源的Matlab Simulink仿真之旅
大数据
智驱力人工智能4 小时前
小区高空抛物AI实时预警方案 筑牢社区头顶安全的实践 高空抛物检测 高空抛物监控安装教程 高空抛物误报率优化方案 高空抛物监控案例分享
人工智能·深度学习·opencv·算法·安全·yolo·边缘计算
七夜zippoe4 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
盟接之桥4 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
忆~遂愿4 小时前
ops-cv 算子库深度解析:面向视觉任务的硬件优化与数据布局(NCHW/NHWC)策略
java·大数据·linux·人工智能