当前位置: 首页 > news >正文

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

目录

1. 什么是动态规划

2. 动态规划步骤

状态表示

状态转移方程

初始化

填表顺序

返回值

3. 例题讲解及具体代码

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个位置的值。

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

class Solution {
public:int tribonacci(int n) {if(n==0) return 0;if(n==1||n==2) return 1;vector 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,是因为在这里也会过大。所以我们要先模一下。

class Solution {
public:int waysToStep(int n) {if(n==1) return 1;if(n==2) return 2;if(n==3) return 4;vector 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];}
};
http://www.jsqmd.com/news/101101/

相关文章:

  • 音乐格式解放攻略:NCM转MP3轻松实现跨平台播放
  • 写了这么多年 Java,这几个神仙技巧你真的用过吗?
  • Zipkin 深度解析:核心原理、集成实战与最佳实践
  • 20 万级新能源 SUV 标杆车型盘点:从技术到体验的全面对比
  • Java新手做毕设:用雷池WAF护SpringBoot项目,避免演示时出洋相
  • 微服务踩坑实录:SpringCloud集群用雷池WAF,解决3个跨服务防护难题
  • Google Drive下载神器:gdrivedl使用完全指南
  • 7.2.2-bpf对tcp请求的监控(项目)
  • AES-GCM加密全流程解析
  • 开源精神再现辉煌:LobeChat推动AI普惠化进程
  • 第三讲:如何用 AI 快速生成可用应用——实战示例
  • NVIDIA Profile Inspector终极指南:从入门到精通的完整图形优化手册
  • 内容解锁神器:Bypass Paywalls Clean 让你告别付费墙烦恼
  • Linux CFS(完全公平调度器)原理与实现细节全解析(2)
  • SillyTavern轻松搞定版本升级:从焦虑到自信的无忧指南
  • 10分钟精通原神智能助手:从零到精通的完整配置指南
  • 视频创作者必看!这7个素材网站
  • LangChain 1.0 VS LangGraph 1.0:智能体我该用哪一个?
  • 比手动排查快10倍:自动化修复Python库缺失问题
  • 怎么查看自己Ubuntu剩余空间有多少个G呢?
  • LobeChat镜像优势详解:为何它成开源大模型前端首选?
  • LobeChat医疗健康问答合规性讨论
  • 5分钟验证:不安装运行时也能测试.NET应用的新方法
  • 手写海康OpenApi签名规范,实现手动调用api(sdk:artemis-http-client)
  • MHT-FE710 光纤组合导航系统技术指南:高精度导航的多接口适配与工程实践
  • 吹爆FreeBuds SE4 ANC的新音效 | 浅聊体验
  • 网盘直链解析终极方案:彻底告别下载限制的完整指南
  • 纪念币预约神器:3步实现高效自动预约的终极指南
  • Unity翻译插件终极指南:3步实现游戏无障碍体验
  • Google Drive高效下载终极指南:解锁无限下载潜力