跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

动态规划经典模型:斐波那契数列及变体

综述由AI生成动态规划解题模版包含状态表示、转移方程、初始化、填表顺序及返回值五个要素。文章通过第 N 个泰波那契数、三步问题、最小花费爬楼梯和解码方法四个实例,演示了斐波那契类问题的状态定义与转移逻辑。提供 Java 代码实现,并针对前两个问题展示了空间复杂度从 O(N) 到 O(1) 的优化方案。

kaikai发布于 2026/3/23更新于 2026/5/2214 浏览
动态规划经典模型:斐波那契数列及变体

一、动态规划解题模版

  1. 状态表示:一般创建一个一维数组 dp,把 dp 表填满,其中的某一个值就是结果。状态表示指 dp 表中元素的含义。
    • 来源:题目要求、经验 + 题目要求,分析问题的过程中的重复子问题
  2. 状态转移方程:dp[i] = ?
  3. 初始化:保证根据状态转移方程填表时不越界
  4. 填表顺序:为了填写当前状态的时候,所需要的状态已经计算过了
  5. 返回值:题目要求 + 状态表示

二、第 N 个泰波那契数

题目描述:第四个数是前三个数的和,第一二三个数定为 0 1 1,返回第 n 个数。

文章配图

题目解析:

解题思路:

  1. 状态表示:dp[i] 表示第 i 个泰波那契数
  2. 状态转移方程:dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]
  3. 初始化:dp[0] = 0, dp[1] = 1, dp[2] = 1
  4. 填表顺序:顺序从左向右填表即可
  5. 返回值:dp[n]

解题代码:

// 时间复杂度:O(N) // 空间复杂度:O(N)
class Solution {
    public int tribonacci(int n) {
        if (n < 3) return n == 0 ? 0 : 1;
        // 创建 dp 表
        int[] dp = new int[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];
    }
}

空间优化:只创建长度为三的数组即可:

// 时间复杂度:O(N) // 空间复杂度:O(1)
class Solution {
    public int tribonacci(int n) {
        if (n < 3) return n == 0 ? 0 : 1;
        // 创建 dp 表
        int[] dp = new int[]{0, 1, 1};
        // 填表
        for (int i = 3; i <= n; i++) {
            int tmp = dp[0];
            dp[0] = dp[1];
            dp[1] = dp[2];
            dp[2] = tmp + dp[0] + dp[1];
        }
        // 返回值
        return dp[2];
    }
}

三、面试题 08.01. 三步问题

题目描述:

文章配图

题目解析:

  • 每一次上楼梯有三个选择:1, 2, 3,返回走到第 n 阶梯有多少种走法

解题思路:

  1. 状态表示:dp[i] 表示第 i 阶的上楼方式种类数
  2. 状态转移方程:dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]
  3. 初始化:dp[0] = 1, dp[1] = 1, dp[2] = 2(小孩有 3 种走法,那么小孩的上一个台阶的可能就是 i-1, i-2, i-3)
  4. 填表顺序:顺序从左向右填表即可
  5. 返回值:dp[n]

解题代码:

// 时间复杂度:O(N) // 空间复杂度:O(N)
class Solution {
    public int waysToStep(int n) {
        if (n < 3) return n;
        // 建立 dp 表
        int[] dp = new int[n + 1];
        // 初始化
        dp[0] = dp[1] = 1; dp[2] = 2;
        // 填表
        for (int i = 3; i <= n; i++) {
            dp[i] = ((dp[i - 1] + dp[i - 2]) % 1000000007 + dp[i - 3]) % 1000000007;
        }
        // 返回值
        return dp[n];
    }
}

四、746. 使用最小花费爬楼梯(easy)

题目描述:

题目解析:

  • 给我们一个 cost 数组,表示走出这一个台阶需要的花费
  • 可以选择第一步从 cost[0] 还是 cost[1] 开始
  • 让我们返回到达楼顶的最小总花费

解题思路:

  1. 状态表示:dp[i] 表示走到第 i 阶的最小花费
  2. 状态转移方程:dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])
  3. 初始化:表的长度要比 cost 大 1,表示楼顶
  4. 填表顺序:顺序从左向右填表即可
  5. 返回值:dp[n]

解题代码:

// 时间复杂度:O(N) // 空间复杂度:O(N)
class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int n = cost.length;
        if (n == 2) return Math.min(cost[0], cost[1]);
        // 状态转移表
        int[] dp = new int[n + 1];
        // 状态转移方程
        for (int i = 2; i <= n; i++) {
            dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
        }
        return dp[n];
    }
}

五、91.解码方法

题目描述:

文章配图

题目解析:

  • 给我们一个编码规则,数字 1 - 26 对应表示字母 A - Z
  • 给我们一个纯数字的字符串,让我们将字符串进行拆分,拆分后的字符串,对应的所有子串都可以对应表示成字母
  • 求可以拆分的种数

解题思路:

  1. 状态表示:dp[i] 表示字符串中 0 到 i 字符的合法拆分结果
  2. 状态转移方程:
    • i 位置上字符为 1 到 9 的字符单独解码成功 dp[i] += dp[i - 1]
    • i 与 i-1 位置上的字符组合是 10 到 26 的合法编码 dp[i] += dp[i - 2]
  3. 初始化:
    • dp[0]:第一个字符不为 0,就 dp[0] = 1,为 0 就返回 0
    • dp[1]:该字符不为 0,dp[1] += dp[0],与第 0 个字符组成合法编码 10 - 26,dp[1] += 1

填表顺序:从左到右 返回值:dp[n - 1]

解题代码:

class Solution {
    public int numDecodings(String s) {
        // 前导 0
        if (s.charAt(0) == '0') return 0;
        int n = s.length();
        char[] ch = s.toCharArray();
        // 只有一个字符
        if (n == 1) return 1;
        int[] dp = new int[n];
        // 初始化
        dp[0] = 1;
        // 初始化第二个元素
        if (ch[1] != '0' && ch[0] != '0') dp[1] += 1;
        int t = (ch[1] - '0') + (ch[0] - '0') * 10;
        if (t >= 10 && t <= 26) dp[1] += 1;
        // 填表
        for (int i = 2; i < n; i++) {
            // 该字符单独组
            if (ch[i] != '0') dp[i] += dp[i - 1];
            // 与前一个字符组
            t = (ch[i] - '0') + (ch[i - 1] - '0') * 10;
            if (t >= 10 && t <= 26) dp[i] += dp[i - 2];
        }
        return dp[n - 1];
    }
}

目录

  1. 一、动态规划解题模版
  2. 二、第 N 个泰波那契数
  3. 三、面试题 08.01. 三步问题
  4. 四、746. 使用最小花费爬楼梯(easy)
  5. 五、91.解码方法
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • KWDB 运维实战:用 SQL 融合 Metrics 指标与 CMDB 资产数据
  • BFS 实现拓扑排序:原理与 LeetCode 实战
  • 知网 AIGC 检测原理与降重实操指南
  • Dify 工作流发布为 MCP Server 实战指南
  • Dify 工作流发布为 MCP Server 实战指南
  • Spring Boot 数据访问与数据库集成实战
  • LLaMA 3.1 模型部署与实战:构建智能聊天机器人
  • 知网AIGC检测怎么过?2026最新降AI率全流程攻略
  • 本地部署 Kimi K2 模型:llama.cpp、vLLM 与 Docker 方案
  • Python 学习路径:从基础语法到机器学习实战指南
  • LeRobot深度解析:5大核心模块构建下一代机器人学习系统
  • C 语言实现 AI 推理:量化、算子融合与内存映射实战
  • 嵌入式 C/C++ 核心考点:内存管理、多态与系统调用
  • OSCP 实战:传递 Net-NTLMv2 哈希攻击原理与实践
  • 汽车雷达在多径存在下的幽灵目标检测——论文阅读
  • JavaScript 简介:从网页脚本到全栈语言
  • Dify MCP Server 插件实战:将工作流发布为第三方可调用服务
  • RabbitMQ 延迟队列插件安装与使用详解
  • 基于 AI 智能体的 C 语言与前端实训项目快速实现指南
  • 双足机器人 2-RSS-1U 并联踝关节设计与运动学分析

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online