DP入门:从爬楼梯到斐波那契,吃透动态规划五步曲,一次搞懂不再怕

发布时间:2026/11/5 14:38:03

DP入门:从爬楼梯到斐波那契,吃透动态规划五步曲,一次搞懂不再怕 动态规划DP是算法面试的“深水区”也是无数人刷题之路的拦路虎。但DP的第一课并不难——LC.70爬楼梯和LC.509斐波那契数这两道“简单题”背后藏着DP的全部DNA重叠子问题、最优子结构、状态转移方程。今天我们不急着刷难题而是用这两道题把“DP五步曲”的思考框架一次讲透。这副骨架未来6天的每一道DP题都要往上挂。悬念先埋这两道题答案数列是同一个数列——爬到第3阶有3种方法恰好就是斐波那契的F(4)。为什么后面揭晓。 题目速览30 秒读懂题目1爬楼梯LC.70每次可以爬1或2个台阶问爬到第n阶有多少种不同的方法。示例n2 → 2 种11 或2示例n3 → 3 种111 / 12 / 21约束n ≤ 45。题目2斐波那契数LC.509F(0)0, F(1)1, F(n)F(n-1)F(n-2)。给定n求F(n)。约束n ≤ 30。 核心思路从暴力递归 → 记忆化 → 自底向上DP → 空间优化四步进化第一步先写暴力解——递归要爬到第n阶最后一步要么从n-1阶迈1步上来要么从n-2阶迈2步上来所以climb(n) climb(n-1) climb(n-2) 边界climb(1) 1, climb(2) 2这和斐波那契的定义一模一样。但复杂度是O(2^n)——n45时约350亿亿次调用直接超时。第二步为什么慢——重叠子问题画出递归树就明白了climb(5)分裂成climb(4)和climb(3)而climb(4)又分裂出climb(3)、climb(2)……同一个子问题被反复计算了无数遍。这些反复出现的子问题就叫重叠子问题Overlapping Subproblems——它是DP存在的第一理由。第三步记忆化——给重复计算加缓存既然climb(3)算过一次就是那个答案为什么还要再算用一个哈希表或数组把“已经算过的n → 结果”存起来递归入口先查缓存查到直接返回。这一改每个子问题只算一次复杂度从O(2^n)骤降到O(n)。这个技巧叫记忆化递归Memoization也就是俗称的“自顶向下的DP”。第四步自底向上DP 空间优化既然climb(n)只依赖climb(n-1)和climb(n-2)我们何必从n往下递归直接从1、2往上推先用1、2推出3再用2、3推出4……一路推到n。这就是自底向上Bottom-Up的DP即狭义的“动态规划”。它比记忆化递归少了函数调用开销和栈溢出风险还能顺手做空间优化。注意到推到第n项时只有前两项还有用更早的历史数据全是“死重”。用两个变量滚动替代整个数组空间降到O(1)。 DP五步曲刻进肌肉记忆状态定义dp[i]是什么含义爬到第i阶的方法总数状态转移方程dp[i]怎么由更小的状态推出dp[i] dp[i-1] dp[i-2]初始化最小规模的子问题答案是什么dp[1] 1, dp[2] 2遍历顺序从小到大保证算dp[i]时依赖项已就绪。返回答案dp[n]。悬念揭晓爬楼梯“最后一步是 1 阶还是 2 阶”的分类与斐波那契“前两项相加”的递推在数学上是同一个二阶线性递推——两道题本质是同一个数列。而记忆化递归与自底向上DP也不是两个算法而是同一个东西的两种写法前者自顶向下“用时才算”后者自底向上“提前算好”状态转移方程完全一致。️ 图解算法手把手走一遍暴力递归树n5重复子问题一眼可见climb(5) / \ climb(4) climb(3) ← climb(3) 第 1 次出现 / \ / \ climb(3) climb(2) climb(2) climb(1) / \ ↑重复 ↑重复 climb(2) climb(1) ... ↑重复climb(3)算2次、climb(2)算3次——n5已开始重复n 45时就是天文数字。记忆化之后每个节点只算一次树坍缩成一条链。自底向上DP表逐格填写n6idp[i]计算过程11初始化只有 1 步一种走法22初始化11 或 233dp[2]dp[1] 2145dp[3]dp[2] 3258dp[4]dp[3] 53613dp[5]dp[4] 85每一格都只看左边两格——这就是无后效性未来的计算只依赖已确定的过去与“怎么走到这一格”的路径无关。空间优化后DP表坍缩成两个滚动变量a1, b2 i1,2 的值 i3: (a,b) (2,3) i4: (a,b) (3,5) i5: (a,b) (5,8) i6: (a,b) (8,13) → 返回 b 代码实现Python Java四种写法全给Python版fromfunctoolsimportlru_cacheclassSolution:# 解法一记忆化递归自顶向下 DPdefclimbStairsMemo(self,n:int)-int:lru_cache(maxsizeNone)# lru_cache 即现成的记忆化缓存defclimb(k:int)-int:ifk2:# 边界dp[1]1, dp[2]2returnkreturnclimb(k-1)climb(k-2)# 转移方程returnclimb(n)# 解法二自底向上 DP 空间优化推荐defclimbStairs(self,n:int)-int:ifn2:returnn a,b1,2# adp[i-2], bdp[i-1]初始对应 dp[1], dp[2]for_inrange(3,n1):a,bb,ab# 滚动前进新 dp[i] dp[i-1] dp[i-2]returnb# 循环结束时 b 即 dp[n]Java版classSolution{// 解法一记忆化递归 privateInteger[]memo;// memo[i] 缓存爬到 i 阶的方法数publicintclimbStairsMemo(intn){memonewInteger[n1];returnclimb(n);}privateintclimb(intk){if(k2)returnk;// 边界if(memo[k]!null)returnmemo[k];// 查缓存算过直接返回memo[k]climb(k-1)climb(k-2);// 转移方程并存缓存returnmemo[k];}// 解法二自底向上 DP 空间优化推荐publicintclimbStairs(intn){if(n2)returnn;inta1,b2;// adp[i-2], bdp[i-1]for(inti3;in;i){intcab;// dp[i] dp[i-1] dp[i-2]ab;// 滚动更新bc;}returnb;// b 即 dp[n]}}⚠️关键提醒LC.509斐波那契数只需把边界改为F(0)0, F(1)1循环从2开始转移方程一字不改——两题同一个数列的代码级证据。⏱️ 复杂度分析面试必问方法时间空间说明暴力递归O(2^n)O(n)栈深度重复计算爆炸记忆化递归O(n)O(n)每个子问题算一次 缓存自底向上DPO(n)O(n)单层循环空间优化版O(n)O(1)两个滚动变量 举一反三3道高频变种题题目变化点思路调整LC.746 使用最小花费爬楼梯每阶有花费求最小总花费转移改为dp[i] min(dp[i-1]cost[i-1], dp[i-2]cost[i-2])“方法数”变“最小值”LC.509 斐波那契数纯数列递推与爬楼梯同构改边界即可剑指 Offer10-II青蛙跳台阶与爬楼梯完全相同原题换皮注意取模 面试追问模拟提前准备Q1为什么朴素递归那么慢因为重叠子问题。递归树有O(2^n)个节点但不同的子问题只有n个剩下全是重复计算。DP的本质贡献就一句话让每个子问题只算一次。判断一个递归树是否“重复计算严重”是识别DP题的第一直觉。Q2怎么判断一个问题能不能用DP两个条件①最优子结构原问题的最优解能由子问题的最优解构造出来②重叠子问题递归展开时子问题反复出现。此外还有隐含的无后效性某状态一旦确定未来的决策不受“如何到达该状态”影响。三条齐备DP就是标配。Q3能更快吗O(logn) 呢可以矩阵快速幂。把递推写成矩阵形式[[1,1],[1,0]]^n用快速幂二分同款的“倍增”思想计算时间O(logn)。面试说出这个思路即可除非面试官要求手写矩阵乘法属于加分项而非必答题。 实战小技巧刷题党必备口诀先写暴力递归再画递归树找重复加缓存变记忆化倒过来推变DP。模板DP五步曲——状态定义、转移方程、初始化、遍历顺序、返回答案。防坑记忆化递归有栈溢出风险n大时优先自底向上。 实际应用场景不止是刷题机器人走网格路径计数每次向右或向下求总路径数骨牌铺满2×n地板方案数统计支付组合统计每次付1元或2元凑够n元有多少种付法组合数学/概率计数型DP是编程化的基础 今日思考题如果每次可以爬1、2或 3个台阶转移方程会变成什么提示dp[i] dp[i-1] dp[i-2] dp[i-3]初始化也要相应调整。你能把空间优化到O(1)吗
延伸阅读

更多相关文章

2026/11/5 17:54:15

AI时代程序员核心能力构建与职业发展策略

1. 项目概述:AI时代程序员的生存法则35岁对于程序员而言,往往被视为职业生涯的分水岭。在这个技术迭代速度以月为单位计算的AI时代,传统编码技能正在以肉眼可见的速度贬值。去年还在用React写页面的前端工程师,今年可能就要面对AI…

2026/10/24 19:05:56

OpenClaw+Polymarket套利系统:市场中性策略实战解析

1. 项目背景与核心逻辑OpenClawPolymarket AI套利系统是一个典型的市场中性策略实现案例,它通过捕捉中心化交易所与链上预测市场之间的定价偏差实现套利。这个系统在2026年创造了从50美元到2980美元的实战成绩,但其本质并非"预测市场"&#xf…

2026/11/4 20:56:14

Flutter与OpenHarmony实现高性能音乐App歌手列表

1. 项目概述与背景在音乐类App中,歌手列表页面是用户发现内容的重要入口之一。这个页面需要同时满足美观性和功能性需求:既要让用户能快速浏览大量歌手信息,又要提供便捷的分类筛选功能。我们基于Flutter框架和OpenHarmony系统开发这个音乐播…

2026/11/5 16:51:33

EasyU优启通PE维护盘实战指南:制作、启动与核心操作全解析

1. 为什么一个PE维护盘值得单独拿出来聊装系统、修引导、救数据、清病毒,这些活儿但凡干过几次的人都知道,真正决定效率的往往不是你手速多快,而是手边那套PE环境靠不靠谱。EasyU(圈内习惯叫优启通)就是在这个场景下被…

2026/11/5 16:26:13

Rust原来很简单二:所有权系统

Part 2 核心篇 —— 所有权系统 本篇覆盖 第 6 ~ 10 章:所有权、借用与引用、生命周期、字符串与切片、内存模型。 ⚠️ 这是全书最重要的一篇。 把它吃透,Rust 从此“很简单”;跳过它,你会处处碰壁。请慢下来,动手敲每一段代码。 第 6 章 所有权:Rust 的第一性原理 6…

2026/11/5 15:00:49

基于Hadoop+Spark的民宿智能推荐系统设计与实现

1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享…

2026/11/5 14:10:30

ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配RS485,解决远距离温度监控难题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑