news 2026/9/16 11:58:44

LeetCode 70. 爬楼梯题解:斐波那契数列的动态规划建模与 O(1) 空间压缩(附 Python / Java / C++ 实现)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 70. 爬楼梯题解:斐波那契数列的动态规划建模与 O(1) 空间压缩(附 Python / Java / C++ 实现)

LeetCode 70. 爬楼梯题解:斐波那契数列的动态规划建模与 O(1) 空间压缩(附 Python / Java / C++ 实现)

【免费下载链接】LeetCode-Book《剑指 Offer》《图解算法数据结构》《Krahets 笔面试精选 88 题》Python, Java, C++ 解题代码项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Book

本篇文章基于《Krahets 笔面试精选 88 题》题解文档 70. 爬楼梯,系统讲解 LeetCode 第 70 题的完整解法:从"最后一步只有跳 1 级或 2 级"的直觉出发,将问题严格建模为斐波那契数列,给出动态规划的四大要素(状态定义、转移方程、初始状态、返回值),并进一步用滚动变量把空间复杂度从 O(N) 压到 O(1)。文末结合当前仓库中三语言解题代码(Python / Java / C++)逐行对照印证,并顺带梳理与本题同源的 509. 斐波那契数、LCR 127. 跳跃训练等变形题。读完你可以彻底掌握"斐波那契类 DP"的通用分析套路,并能够举一反三解决同族题目。

一、问题理解:从"跳法"到递推关系

题目要求计算爬 n 级台阶的不同方法数,约束是每次只能爬 1 级或 2 级。题解文档给出了一个非常干净的建模视角:关注青蛙(或人)的最后一步

设跳上 n 级台阶有 f(n) 种跳法。在所有跳法中,最后一步只有两种情况:

  1. 最后跳 1 级:此时已经站在第 n-1 级台阶上,前 n-1 级台阶的跳法数为 f(n-1);
  2. 最后跳 2 级:此时已经站在第 n-2 级台阶上,前 n-2 级台阶的跳法数为 f(n-2)。

由于两种情况的最后一步互斥,总的跳法数就是两者之和:

f(n) = f(n-1) + f(n-2)

这正是斐波那契数列的递推性质。因此本题可完全转化为"求斐波那契数列的第 n 项",唯一区别在于初始值不同:

问题f(0)f(1)f(2)
爬楼梯(青蛙跳台阶)112
标准斐波那契数列011

以爬楼梯为例验证:f(0)=1(不跳视为 1 种空方案,便于递推)、f(1)=1(跳 1 级)、f(2)=2(1+1 或 2),f(3)=f(2)+f(1)=3(111、12、21),与直觉完全吻合。

二、动态规划解析:四要素拆解

题解文档将动态规划解法明确拆为四个要素,这是复用的核心框架:

  • 状态定义:设 dp 为一维数组,其中 dp[i] 的值代表斐波那契数列(即爬楼梯跳法数)的第 i 个数字;
  • 转移方程dp[i + 1] = dp[i] + dp[i - 1],即对应数列定义f(n + 1) = f(n) + f(n - 1)
  • 初始状态dp[0] = 1, dp[1] = 1,初始化前两个数字;
  • 返回值dp[n],即斐波那契数列(爬楼梯跳法数)的第 n 个数字。

需要说明:原文档插图(台阶跳法示意)托管在力扣图床,仓库内并未保存该图片资源,因此本文以文字形式完整还原了该图所要传达的递推逻辑——第 n 级跳法由第 n-1 级与第 n-2 级两种"最后一步"的跳法数相加得到。

三、状态压缩:空间复杂度从 O(N) 降到 O(1)

如果严格按 dp 数组实现,需要新建长度为 n 的列表,空间复杂度为 O(N)。但注意观察转移方程:

dp 列表第 i 项只与第 i-1 和第 i-2 项有关,更早的历史状态在计算完成后不再被引用。

因此只需初始化三个整型变量sumab,利用辅助变量sum暂存a + b,再让a, b两数字交替前进(滚动更新)即可。省去了整个 dp 列表空间,空间复杂度降至 O(1),这就是"滚动变量"式的状态压缩。这一思路在仓库内的三语言代码中均有直接体现(详见下一节)。

四、三语言代码实现(仓库源码对照)

原文档给出了 Python、Java、C++ 三种实现,且当前仓库 selected_coding_interview/codes 目录下保存了与文档完全一致的工程化源码,可直接对照阅读。

Python 实现

文档中的核心解法:

class Solution: def climbStairs(self, n: int) -> int: a, b = 1, 1 for _ in range(n - 1): a, b = b, a + b return b

仓库中的工程化版本位于 selected_coding_interview/codes/python/lc_70_climbing_stairs.py,代码结构分为Solution Code(解题类)、Test Case(测试用例区)与Driver Code(驱动入口)三部分,并from include import *引入了仓库公共工具模块(见 selected_coding_interview/codes/python/include)。注意 Python 中a, b = b, a + b的元组赋值天然完成"同时更新",无需sum辅助变量。

Java 实现

class Solution { public int climbStairs(int n) { int a = 1, b = 1, sum; for(int i = 0; i < n - 1; i++){ sum = a + b; a = b; b = sum; } return b; } }

仓库中的完整版本位于 selected_coding_interview/codes/java/lc_70_climbing_stairs/lc_70_climbing_stairs.java,以package lc_70_climbing_stairs;组织包结构,同样包含Solution类与带main方法的驱动类。由于 Java 不支持元组同时赋值,这里显式使用sum临时变量完成a -> bb -> sum的滚动更新。

C++ 实现

class Solution { public: int climbStairs(int n) { int a = 1, b = 1, sum; for(int i = 0; i < n - 1; i++){ sum = a + b; a = b; b = sum; } return b; } };

仓库中的完整版本位于 selected_coding_interview/codes/cpp/lc_70_climbing_stairs/lc_70_climbing_stairs_s1.cpp,是三种语言中唯一补全了可运行测试驱动的版本:其main函数中构造了测试用例n = 2,调用slt->climbStairs(n)后通过cout << res << endl;输出结果(预期输出 2),可以直接编译运行验证算法正确性。该文件还#include "../include/include.hpp"引用了 C++ 公共头文件目录。

三种语言的循环次数均为n - 1,因为初始b = f(1) = 1已覆盖第 1 项,之后每迭代一次把指针向前推进一级,n-1 轮后b恰好为f(n)。以 n=2 为例:只迭代 1 轮,b = 1 + 1 = 2,正确。

五、复杂度分析

  • 时间复杂度 O(n):计算 f(n) 需循环 n 次,每轮循环内只做常数次加法与赋值,单轮开销 O(1),总开销 O(n);
  • 空间复杂度 O(1):只使用absum(或循环变量)等常数个变量,不随 n 增长。

六、同类变形题:从仓库中看斐波那契族题目的演进

理解了"最后一步"的建模方式后,同一思想可以迁移到仓库中另外两道同源题目:

  1. 509. 斐波那契数:本题的直接母题。区别仅在初始值f(0)=0, f(1)=1,且循环体写为a, b = b, a + b; return a。仓库源码见 selected_coding_interview/codes/python/lc_509_fibonacci_number.py。对照阅读可以清晰看到"初始值不同 → 返回变量不同"这一唯一差异;
  2. LCR 127. 跳跃训练(对应剑指 Offer 10-II 青蛙跳台阶):与本题题目背景完全一致,但额外引入了大数越界防护——因为随 n 增大 f(n) 会超过 Int32/Int64 范围,需要在每轮循环中执行sum = (a + b) % 1000000007。其依据是模运算分配律(x + y) ⊙ p = (x ⊙ p + y ⊙ p) ⊙ p,逐轮取模与最终取模等价,可保证中间结果不溢出。

这条"爬楼梯 → 斐波那契 → 取模防溢出"的进阶路径,正是面试中考察动态规划基础能力的经典组合,建议三题连刷对照。

七、小结

本文围绕 70. 爬楼梯题解文档 的核心内容,完整梳理了该题从问题建模(最后一步分类)、递推归纳(斐波那契数列)、动态规划四要素,到状态压缩(O(N) → O(1))的完整推理链条,并给出了 Python / Java / C++ 三种语言的可运行代码及仓库源码位置。掌握这套"斐波那契类 DP"的分析框架后,你可以快速迁移到跳跃训练、斐波那契数等一切具有f(n) = f(n-1) + f(n-2)结构的题目中。

【免费下载链接】LeetCode-Book《剑指 Offer》《图解算法数据结构》《Krahets 笔面试精选 88 题》Python, Java, C++ 解题代码项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Book

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 11:57:04

滑动窗口算法:高效解决连续子数组问题的利器

1. 滑动窗口算法概述滑动窗口&#xff08;Sliding Window&#xff09;是一种用于处理数组/链表子区间问题的高效算法技巧。它通过维护一个动态变化的窗口来避免重复计算&#xff0c;将许多看似需要O(n)时间复杂度的问题优化到O(n)级别。我第一次接触这个算法是在解决LeetCode上…

作者头像 李华
网站建设 2026/9/16 11:56:27

Skeleton响应式网格模板拆解:栅格计算、样式改造与单页网站实践

简介&#xff1a;面向网页设计课程与毕业设计的实战模板包&#xff0c;适合正在完成Web开发类项目或希望快速搭建单页作品的学生。压缩包内含178个文件&#xff0c;包括大量png/jpg展示图、gif动效、CSS/JavaScript/PHP源码、HTML入口页及字体图标文件&#xff0c;包体约778KB&…

作者头像 李华
网站建设 2026/9/16 11:55:14

LFM信号匹配滤波中窗函数选型的PSR与隔离度权衡

简介&#xff1a;本资源是一份面向信号处理初学者与雷达/通信方向工程实践者的MATLAB仿真源码&#xff0c;聚焦LFM&#xff08;线性调频&#xff09;信号匹配滤波性能优化问题&#xff0c;重点分析矩形窗、汉明窗、海明窗、布莱克曼窗等不同类型窗函数对峰值旁瓣比&#xff08;…

作者头像 李华
网站建设 2026/9/16 11:54:49

FPGA原型验证:突破USB/MIPI/TDC物理层瓶颈的实战方法论

1. 原型芯片验证不是“跑通就行”&#xff0c;而是研发节奏的生死线你有没有经历过这样的场景&#xff1a;FPGA原型板焊好&#xff0c;代码烧进去&#xff0c;LED灯亮了&#xff0c;UART吐出“Hello World”&#xff0c;团队群里发个&#x1f389;&#xff0c;大家以为验证完成…

作者头像 李华
网站建设 2026/9/16 11:52:47

基于Matlab的心脏病预测模型构建与实践

1. 项目背景与核心价值心血管疾病&#xff08;CVDs&#xff09;是全球头号健康杀手&#xff0c;每年导致约1790万人死亡&#xff0c;占全球总死亡人数的31%。这个基于Matlab的二元分类项目&#xff0c;使用Kaggle心脏病数据集&#xff0c;通过机器学习方法构建预测模型&#xf…

作者头像 李华
网站建设 2026/9/16 11:52:45

Python魔法方法详解与实战应用

1. Python魔法方法入门指南第一次看到__init__或__str__这样的方法时&#xff0c;很多Python开发者都会感到困惑。这些被双下划线包围的特殊方法&#xff0c;正是Python语言中最强大的特性之一。作为有五年Python工程经验的开发者&#xff0c;我发现合理使用魔法方法能让代码更…

作者头像 李华