《LeetCode 1137 第N个泰波那契数 和 LeetCode 三步问题》

一、题目

二、做题思路

2.1 状态表示(核心基础)

状态表示即明确 dp 表中每个元素所代表的含义。其来源通常有三:直接依据题目要求 、结合经验对题目进行抽象、或在分析过程中提炼重复子问题 。本题中,题目已明确要求:数组下标 i 对应第 i 个泰波那契数,因此我们定义 dp[i] 表示第 i 个泰波那契数的值 。这是后续推导的基石,必须首先确定。

2.2 状态转移方程(关键难点)

状态转移方程描述了 dp[i] 与前面若干状态之间的递推关系 ,来源于题目给出的递推公式。本题直接依据泰波那契数列的定义:

dp[i] = dp[i-1] + dp[i-2] + dp[i-3](其中 i ≥ 3

该方程将大问题拆解为规模更小的子问题 ,是整个动态规划过程的核心纽带

2.3 初始化(边界防护)

初始化是为了保证填表过程中数组访问不越界 ,同时为递推提供起始条件 。由于状态转移方程需要用到前三个状态,当 i < 3 时无法通过方程计算,因此必须单独给出初始值。本题题目已明确:

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

这些初始值是递推的**"种子"** ,是正确计算的必要前提

2.4 填表顺序(递推方向)

填表顺序取决于当前状态所依赖的前驱状态 ,必须保证计算某一状态时,其所需的所有前置状态均已就绪 。本题中,dp[i] 依赖 i-1i-2i-3(均小于 i),因此采用 从左到右 (即下标从小到大)的顺序依次填充 dp 表,可确保每次计算时所需数据已经完备

2.5 返回值(目标映射)

返回值即最终需要向调用者 输出的结果,由题目要求与状态表示 共同决定。本题要求返回第 n 个泰波那契数,而 dp[n] 正好表示该值,因此直接返回 dp[n] 。若 n 小于初始边界,则直接返回对应的初始值,避免越界访问。

三、代码

cpp 复制代码
#include <vector>

using  namespace std;

class Solution {
public:
    int tribonacci(int n)
    {
        //3.初始化
        if (n == 0) return 0;
        if (n == 1 || n == 2) return 1;

        vector<int> dp(n + 1);//1.状态表示,一个下标对应一个Tn元素

        //3.初始化dp表
        dp[0] = 0, dp[1] = 1, dp[2] = 1;

        //2.状态转移方程 dpn = dpn-1 + dpn-2 + dpn-3
        //4.填表顺序
        for (int i = 3; i <= n; i++)
        {
            dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];
        }

        //5.返回值
        return dp[n];
    }
};

四、流程图

五、题目

六、做题思路

6.1 状态表示(核心基础)

本题要求计算到达第 i 级台阶 的所有不同走法总数。因此定义 dp[i] 表示从地面(第 0 级)走到第 i 级台阶的方法数 。该定义直接来源于题目要求,且以位置为结尾 进行统计,是后续推导的出发点

6.2 状态转移方程(关键难点)

小孩一次可以上 1 阶、2 阶或 3 阶 ,那么到达第 i 级台阶的最后一步 可能来自 i-1i-2i-3。由于这三种方式是互斥且完备 的,所以总方法数等于三者之和:

dp[i] = dp[i-1] + dp[i-2] + dp[i-3] (其中 i ≥ 4)。

同时,根据示例可验证初始值:dp[1]=1dp[2]=2dp[3]=4,与递推公式吻合。

6.3 初始化(边界防护)

递推公式依赖前三个状态,因此 i=1,2,3 必须手动赋值

dp[1] = 1 (仅 1 步),dp[2] = 2 (1+1 或 2),dp[3] = 4 (1+1+1、1+2、2+1、3)。

此外,题目提示结果可能很大,需对 100000007 (即 1e8+7)取模,每次相加后及时取模,防止溢出

6.4 填表顺序(递推方向)

计算 dp[i] 必须依赖 dp[i-1]dp[i-2]dp[i-3],这些下标均小于 i。因此必须从左到右 (即下标从小到大)依次填充 dp 表,保证每个状态计算时,其所有前置状态均已就绪

6.5 返回值(目标映射)

题目要求返回n 级台阶的走法数 ,而 dp[n] 正表示该值,因此直接返回 dp[n] 。若 n 在初始范围内(1~3),则直接返回对应的初始化值,无需进入递推循环,避免越界访问

七、代码展示

cpp 复制代码
#include <vector>
using namespace std;
class Solution {
public:
    int waysToStep(int n)
    {
        //处理边界情况
        if (n == 1) return 1;
        if (n == 2) return 2;
        if (n == 3) return 4;

        const int Mod = 1e9 + 7;//模数 

        //1.创建dp表
        vector<int> dp(n + 1);
        //3. 初始化
        dp[1] = 1, dp[2] = 2, dp[3] = 4;

        //2.状态转移方程
        for (int i = 4; i <= n; i++)
        {
            //4. 填表顺序(从左到右)
            dp[i] = ((dp[i - 3] + dp[i - 2]) % Mod + dp[i - 1]) % Mod;
        }
        //5. 返回值     
        return dp[n];
    }
};

八、流程图

相关推荐
c++之路1 小时前
C++跨平台(九):跨平台字节序统一处理
开发语言·arm开发·c++
wabs6661 小时前
关于动态规划【力扣718.最长重复子数组的思考】
算法·leetcode·动态规划
技术小黑1 小时前
CNN算法实战系列08 | ResNeXt-50算法实战与猴痘病识别
人工智能·算法·cnn
Full Stack Developme2 小时前
Java 漏斗算法 及应用场景
java·开发语言·算法
atunet2 小时前
关于稀疏图结构的高效存储与遍历算法设计的技术7
算法
ysa0510302 小时前
【并查集】判环,深搜
数据结构·c++·算法·深度优先
Jerry2 小时前
LeetCode 704. 二分查找
算法
Gp7HH6hrE3 小时前
P1118 [USACO06FEB] Backward Digit Sums G/S
算法·深度优先
AI科技星3 小时前
32维超复数流形中意识信息场与物质耦合的拓扑动力学
人工智能·学习·算法·数据挖掘·回归·乖乖数学·全域数学