递归实现斐波那契数列需避免重复计算和栈溢出,基础写法f(n)=f(n−1)+f(n−2)(f(0)=0,f(1)=1)效率低,应改用记忆化或迭代优化。

用递归实现斐波那契数列很简单,但不加限制会严重拖慢甚至导致浏览器卡死或栈溢出。关键在于避免重复计算和控制调用深度。
基础递归写法(不推荐直接使用)
最直观的写法是按定义:f(n) = f(n−1) + f(n−2),边界是 f(0)=0,f(1)=1:
function fib(n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}
问题在于时间复杂度高达 O(2ⁿ)。比如算 fib(40),要调用函数上千万次,浏览器明显卡顿;n 超过 50 就可能触发“Maximum call stack size exceeded”错误。
加记忆化(Memoization)——推荐做法
把已算过的值存起来,下次直接返回,时间复杂度降到 O(n):
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
立即学习“Java免费学习笔记(深入)”;
- 用一个对象或 Map 缓存结果,键为 n,值为 fib(n)
- 每次进入函数先查缓存,命中就直接返回
- 没命中再递归计算,并把结果存入缓存
function fib(n, memo = {}) {
if (n in memo) return memo[n];
if (n <= 1) return n;
memo[n] = fib(n - 1, memo) + fib(n - 2, memo);
return memo[n;
}
限制输入范围,防意外崩溃
用户可能传入负数、非数字或过大数值。加上简单校验更健壮:
- 检查是否为有效非负整数,否则提前返回或抛错
- 设定合理上限(如 n ≤ 10000),超出时拒绝执行
- 对超大 n 可降级为循环实现(迭代更安全)
function fib(n) {
if (!Number.isInteger(n) || n < 0) throw new Error('n must be non-negative integer');
if (n > 10000) throw new Error('n too large, use iterative version instead');
const memo = {};
function calc(x) {
if (x in memo) return memo[x];
if (x <= 1) return x;
memo[x] = calc(x - 1) + calc(x - 2);
return memo[x];
}
return calc(n);
}
备选:迭代实现(更稳妥)
递归不是必须的。迭代用两个变量滚动更新,空间 O(1)、时间 O(n),无栈溢出风险,适合生产环境:
function fib(n) {
if (n < 0 || !Number.isInteger(n)) throw new Error('invalid input');
let a = 0, b = 1;
if (n === 0) return a;
for (let i = 2; i <= n; i++) {
[a, b] = [b, a + b];
}
return b;
}
不复杂但容易忽略边界和类型检查,实际项目中优先考虑迭代或带缓存的递归。

















