从爬楼梯到算斐波那契,我终于弄懂了递归和动态规划这俩 "磨人精"

最近在代码界摸爬滚打,总被两个词按在地上摩擦 ------ 递归和动态规划。这俩货就像数学题里的 "小明",天天换着花样折磨人,今天就来好好扒一扒它们的底裤。

递归:自己调自己的 "套娃大师"

递归这东西,说白了就是函数自己喊自己的名字。就像小时候问妈妈 "我从哪来的",妈妈说 "你是妈妈生的",再问 "妈妈从哪来的",妈妈说 "外婆生的"... 一直问到祖宗十八代,这就是递归的精髓 ------ 找规律 + 找出口

比如算个阶乘,用递归(时间复杂度过高)写出来是这样:

js 复制代码
function mul(n){

   if(n === 1){ // 出口:问到祖宗了

       return 1

   }

   return n * mul(n-1) 

}

这代码简洁得像诗,但算个斐波那契数列就露馅了。那个 1,1,2,3,5,8... 的数列,递归写法看着简单:

递归的 "中年危机":重复计算让 CPU 原地冒烟

js 复制代码
function fb(n){

   if(n === 1 || n === 2){

       return 1

   }

   return fb(n-1) + fb(n-2)

}

这代码算个 n=10 还行,要是算 n=40,能让你喝杯咖啡回来还没出结果。就像你查快递单号,每次都要从快递员刚取件的时候查起,哪怕昨天刚查过。

给递归装个 "备忘录":记忆化搜索救场

比如爬楼梯问题:一次能爬 1 或 2 阶,到第 n 阶有几种走法?

后来我灵机一动,给递归加了个小本本(数组 f):

js 复制代码
const f = []
var climbStairs = function (n) {
    if (n === 1 || n === 2) {
        return n
    }
    if (f[n] === undefined) { // 查小本本,没记过才计算
        f[n] = climbStairs(n - 1) + climbStairs(n - 2)
    }
    return f[n]
};

这招叫 "记忆化搜索"(提效),相当于把算过的结果记在通讯录里,下次直接拨号不用重新查号。

后来才发现,这代码就像给老年机装了智能手机的通讯录 ------ 思路对但效率不够。全局数组 f 在多组测试用例下会残留历史数据,而且递归调用本身就有函数栈的开销,n 太大时还是扛不住。

彻底换个活法:动态规划的 "自底向上" 哲学

  • 站在已知的角度,通过已知来定位未知 最后改用纯动态规划找到动态方程)写法,直接逆袭:
js 复制代码
var climbStairs = function (n){
    const f = []
    // 先搞定已知的1楼和2楼
    f[1] = 1
    f[2] = 2
    // 从3楼开始往上爬,每步都踩在前人的肩膀上
    for(let i = 3;i<=n;i++){
        f[i] = f[i-1] + f[i-2]
    }
    return f[n]
 }

这思路就像盖楼,从 1 层开始一层层往上盖,每一层的建材都直接用前两层的,根本不用回头看。没有递归的函数调用开销,也没有重复计算,效率直接拉满。

总结:三种写法的生存现状

写法 特点 适合场景
纯递归 代码简洁如诗 理解思路用,n≤30
记忆化搜索 加了缓存的递归 教学演示,n≤1000
动态规划 自底向上迭代 实际开发,n多大都不怕

总结:什么时候该套娃,什么时候该记笔记?

  • 递归适合简单问题或调试时用,写起来爽,但容易重复劳动

  • 动态规划适合复杂问题,虽然前期要多写几行,但跑起来飞快

  • 记住:所有动态规划问题,先建个空数组当小本本准没错

现在终于明白,递归是浪漫的诗人,只顾优雅不管效率; 动态规划是务实的会计,每一笔账都记得清清楚楚。 下次再遇到这俩货,我可不会再被它们忽悠了!

相关推荐
鼎道开发者联盟21 分钟前
鼎享会 | OpenClaw Control UI 前端架构全解析:自研 UI 对接 Server 实操指南
前端·ui·架构·openclaw·control ui
尘世中一位迷途小书童23 分钟前
一套完整的给予ceium封装的组件库,可满足企业级开发
前端
Z_Wonderful24 分钟前
微前端:Webpack 配置 vs Vite 配置 超清晰对比
前端·webpack·node.js
thankseveryday26 分钟前
Three.js 把 Blender 绘制的曲线(Bezier / 曲线) 导入 Three.js 并作为运动路径 / 动画路径使用
开发语言·javascript·blender
码云数智-园园29 分钟前
HTTPS是如何工作的?从HTTP到HTTPS的加密演进
前端
隔窗听雨眠37 分钟前
HTML头部元信息避坑指南
前端·html
Gauss松鼠会44 分钟前
【openGauss】openGauss 磁盘引擎之 ustore
java·服务器·开发语言·前端·数据库·经验分享·gaussdb
LIO1 小时前
前端响应式页面开发全攻略:核心技术 + 实现效果 + 实战指南
前端·响应式设计
indexsunny1 小时前
互联网大厂Java面试实战:Spring Boot微服务与Kafka消息队列深度解析
java·spring boot·微服务·面试·kafka·消息队列·电商
得物技术1 小时前
AI驱动:从运营行为到自动化用例的智能化实践|得物技术
前端·ai编程·全栈