1137. 第 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

算法原理

这是一道使用动态规划解决的题目,所以按照 5 步来进行处理

  1. 创建一个 dp 数组,确定状态表示:状态表示指 dp 数组第 i 个元素代表着什么,在这道题目里,第 i 个元素 dpidpidpi 代表了第 i 个泰波那契数 TiT_iTi
  2. 确定状态转移方程:指第 i 个泰波那契数 TiT_iTi 的计算方式,题目中给出的是 Ti+3=Ti+Ti+1+Ti+2T_{i+3} = T_i + T_{i+1} + T_{i+2}Ti+3=Ti+Ti+1+Ti+2,只要让 i 减去 3,就可以得到 Ti=Ti−1+Ti−2+Ti−3T_{i} = T_{i-1} + T_{i-2} + T_{i-3}Ti=Ti−1+Ti−2+Ti−3,也就是说 dpi=dpi−1+dpi−2+dpi−3dpi = dpi - 1 + dpi - 2 + dpi - 3dpi=dpi−1+dpi−2+dpi−3
  3. 初始化:用来保证计算时数组不越界,如果 i = 0,dp0=dp−1+dp−2+dp−3dp0 = dp-1 + dp-2 + dp-3dp0=dp−1+dp−2+dp−3,这是会越界的,dp1,dp2dp1, dp2dp1,dp2 在计算时也是一样,所以要先初始化这三个值。题目中已经给出,dp0=T0=0,dp1=T1=1,dp2=T2=2dp0 = T_0 = 0,dp1 = T_1 = 1,dp2 = T_2= 2dp0=T0=0,dp1=T1=1,dp2=T2=2
  4. 填表顺序:由于新算出来的值依赖于之前的三个值,所以填表是从左向右的
  5. 返回值:题目要得到第 n 个泰波那契数的值,所以返回 dpndpndpn

代码

cpp 复制代码
class Solution {
public:
    int tribonacci(int n) {
        int dp[38] = { 0 };
        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];
    }
};

空间优化

以计算第 5 个泰波那契数 T5=7T_5 = 7T5=7 为例:

当计算出 T3=2T_3 = 2T3=2,计算 T4=4T_4 = 4T4=4 时,可以发现只需要用到 T1,T2,T3T_1, T_2,T_3T1,T2,T3。 T0=0T_0 = 0T0=0 已经不需要使用了。因此每当计算出一个泰波那契数的时候,之前算出来过的一个数就可以丢弃了

在这样的条件下,不需要使用一个数组来保存得到的所有泰波那契数,只要用三个变量 a, b, c 保存计算 TiT_iTi 时需要的数 Ti−1,Ti−2,Ti−3T_{i-1}, T_{i-2}, T_{i-3}Ti−1,Ti−2,Ti−3 即可

优化后的代码

cpp 复制代码
class Solution {
public:
    int tribonacci(int n) {
        if (n == 0) return 0;
        else if (n == 1 || n == 2) return 1;

        int a = 0, b = 1, c = 1, d = 0;
        for (int i = 3;i <= n;++i)
        {
            d = a + b + c;
            a = b;
            b = c;
            c = d;
        }
        return d;
    }
};
相关推荐
sm_926787058 小时前
RFID 标签打印的技术实现要点与二次开发实践
java·大数据·前端·c++·编辑器
by209998 小时前
C++ 多态:同一个基类接口,调用不同的函数
开发语言·c++·经验分享·多态
colinu9 小时前
C++ 异步任务与线程生命周期:`std::async`、`future`、`thread`、`jthread` 与协作式退出
java·jvm·c++
wuminyu9 小时前
ForkJoinPool窃取线程在扫描其他WorkQueue时的随机采样算法与Phase线程挂起唤醒机制解析
java·linux·c语言·jvm·c++
longlongzihan9 小时前
链表找环:Floyd 判圈算法(LeetCode 141 & 142 )
c++·算法·leetcode·链表
liulilittle10 小时前
Linux 下 select 测试函数
linux·服务器·网络·数据库·c++·select·c
无忧.芙桃10 小时前
C++语言原理与实践(十二):list类的底层实现
c++·windows·list
沫璃染墨10 小时前
《Linux工程实践篇(二):线程池实战——从线程安全单例到完整源码实现》
linux·开发语言·c++·单例模式·设计模式·系统架构
有只小白叫岳飒11 小时前
c++智能指针 unique_ptr与函数调用
c++
Leo.yuan11 小时前
Kafka+Flink拼凑,还是FineDataLink 5.0一体化?实时数据处理的两种思路
c++·mfc