【动态规划专栏】专题一:斐波那契数列模型--------1.第N个泰波那契数

简介: 【动态规划专栏】专题一:斐波那契数列模型--------1.第N个泰波那契数


题目来源

本题来源为:

Leetcode1137. 第 N 个泰波那契数

题目描述

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

T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2

给你整数 n,请返回第 n 个泰波那契数 Tn 的值。

题目解析

这里我们首先可以先将题目的公式变形一下:

通过一个简单例子来理解此题目:

T0 T1 T2值题目中已经给出,而T4的值是T0 +T1+ T2的结果,而T5的值是T1 +T2+ T3的结果,依次内推…

算法原理

在讲解此题的算法原理之前,我们先了解一下动态规划:

[动态规划 dynamic programming」是一个重要的算法范式,它将一个问题分解为一系列更小的子问题,并通过存储子问题的解来避免重复计算,从而大幅提升时间效率。

可能此概念对于初学者来说很抽象,我们通过本题为例,给出动态规划的一般解决思路:

动态规划做题流程,一般会定义一个dp(动态规划的缩写)(一位或者二维数组)

然后想办法把里面的值给填满,里面的某一个值可能就是我们的最终结果!

举个例子:

动态规划基本上分为五步:

1.状态表示

2.状态转移方程

3.初始化

4.填表顺序

5.返回值

其中状态转移方程由状态表示推出,而3.4.5步则为处理细节问题。

接下来将通过本题为例来讲解这五步如何处理:

1.状态表示

首先什么是状态表示呢?

简单点的说:状态表示就是dp表里面值的含义

那么具体怎么知道里面值所代表的含义呢?

基础有三种方式

1.1题目要求

1.2经验+题目要求(大多数)

1.3分析问题过程中,发现重复子问题(难点)

当然也不仅仅与此,后面也会再接触更多的方法!

那么根据本题目要求,

dp[i]表示:第i个泰波那契的值

2.状态转移方程

状态转移方程是什么?

通俗来说,就是推出一个式子,让dp[i]等于什么

根据本题要求,我们计算一个值时,需要知道它前面的三个值。

计算i位置的值(dp[i])时,需要知道i-1,i-2,i-3的值,那么i-1位置的值又怎么求呢?在回顾一下我们的状态表示,dp[i]表示:第i个泰波那契的值 那么i-1位置的值不就是dp[i-1],以此内推…

分析到这,我们的状态转移方程已经出来了:

dp[i] = dp[i-3] + dp[i-2] + dp[i-1]

3.初始化

什么是初始化?

就是要保证填表的时候不越界

那么怎么填,其实就是根据状态转移方程,害怕越界访问,进行相关初始化 而本题的题目其实已经告诉我们了:

当i为0,1,2时就会产生越界访问,而本题的题目已经将这三个位置的值已经告诉我们了:

因此初始化为:

dp[0]=0
dp[1]=1
dp[2]=2

4.填表顺序

根据状态转移方程,我们计算dp[i]位置的值需要i-1与i-2位置的值,因此我们的填表顺序为:从左往右

5.返回值

根据题目要求返回第 n 个泰波那契数 Tn 的值。

而我们的状态表示 :dp[i]表示:第i个泰波那契的值

因此返回dp[n]

代码实现

动态规划的代码基本就是固定的四步:

1.创建dp表
2.初始化
3.填表
4.返回值
class Solution 
{
public:
    int tribonacci(int n) 
    {
        // 1.创建dp表
        // 2.初始化
        // 3.填表
        // 4.返回值
      
        //处理一下边界情况:
        if(n==0)
            return 0;
        if(n==1||n==2)
            return 1;
        //创建dp表
        vector<int> dp(n+1);
        //初始化
        dp[0]=0;
        dp[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];
    }
};

注意n的取值范围:

0 <= n <= 37

因此要处理一下边界情况:

//处理一下边界情况
 if(n==0)
    return 0;
 if(n==1||n==2)
    return 1;

时间复杂度:O(N)

空间复杂度:O(N)

相关文章
|
10月前
|
缓存 自然语言处理 算法
大模型意图识别工程化实践
本文重点介绍大模型意图识别能力在智能电视核心链路中的落地过程和思考,对比了基础模型、RAG 、以及7b模型微调三种方案的优缺点。
4762 121
|
10月前
|
设计模式 存储 缓存
「全网最细 + 实战源码案例」设计模式——享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,旨在减少大量相似对象的内存消耗。通过分离对象的内部状态(可共享、不变)和外部状态(依赖环境、变化),它有效减少了内存使用。适用于存在大量相似对象且需节省内存的场景。模式优点包括节省内存和提高性能,但会增加系统复杂性。实现时需将对象成员变量拆分为内在和外在状态,并通过工厂类管理享元对象。
381 92
|
传感器 机器学习/深度学习 数据采集
2022年第十一届认证杯数学中国数学建模国际赛小美赛:C 题 对人类活动进行分类 建模方案及代码实现
本文提供了2022年第十一届认证杯数学中国数学建模国际赛小美赛C题"对人类活动进行分类"的建模方案和Python代码实现,包括数据预处理、特征提取、LSTM网络模型构建和训练评估过程。
406 11
2022年第十一届认证杯数学中国数学建模国际赛小美赛:C 题 对人类活动进行分类 建模方案及代码实现
|
12月前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
11320 5
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
存储 安全 网络安全
|
前端开发 JavaScript 异构计算
简述浏览器的渲染原理
浏览器渲染原理主要包括以下步骤:1)解析HTML文档生成DOM树;2)解析CSS生成CSSOM树;3)结合DOM与CSSOM生成渲染树;4)布局计算(回流)确定元素大小和位置;5)绘制(Paint)将节点转为图形内容;6)合成(Composite)多层图像。整个过程从文档解析到最终输出完整网页,并通过优化技术提升性能。
|
缓存 资源调度 JavaScript
npx与npm的差异解析,以及包管理器yarn与Node版本管理工具nvm的使用方法详解
npx与npm的差异解析,以及包管理器yarn与Node版本管理工具nvm的使用方法详解
1003 0
|
SQL 数据挖掘 Serverless
SQL 窗口函数简直太厉害啦!复杂数据分析的超强利器,带你轻松攻克数据难题,快来一探究竟!
【8月更文挑战第31天】在数据驱动时代,高效处理和分析大量数据至关重要。SQL窗口函数可对一组行操作并返回结果集,无需分组即可保留原始行信息。本文将介绍窗口函数的分类、应用场景及最佳实践,助您掌握这一强大工具。例如,在销售数据分析中,可使用窗口函数计算累计销售额和移动平均销售额,更好地理解业务趋势。
456 0
|
运维 监控 负载均衡
什么是系统可用性?如何提升可用性?
本文探讨了系统可用性的概念、计算方法及其重要性。可用性指系统能在预定时间内正常运行的比例,计算公式为:(运行时间)/(运行时间+停机时间)。文章列举了不同级别的可用性对应的停机时间,并介绍了提升系统可用性的多种策略,包括冗余设计、故障检测与自动恢复、数据备份与恢复、负载均衡、容错设计、定期维护与更新及使用高可用性云服务和网络优化。这些措施有助于构建更加稳定可靠的系统。
2177 0