自己调用自己的函数,看似绕晕,却是解决很多问题的利器。
👋 你好,我是 Evan ,一名计算机专业的学长,也是《大一突围》专栏的作者。刚学递归时,我对着 factorial(n) 看了半天,死活想不通"函数为什么能调用自身"。直到画了几次调用栈,才豁然开朗。今天我就用阶乘和斐波那契数列这两个经典例子,带你彻底搞懂递归------不只是语法,更是背后的思维模型。
欢迎来到 《大一突围》 专栏。

一、什么是递归?
递归就是函数在定义中调用自身。它把一个复杂问题分解成规模更小的子问题,直到达到最简单的"基准条件"。

递归的两个核心要素
-
基准条件(base case) :不再递归,直接返回结果。例如阶乘中
0! = 1。 -
递归条件(recursive case):将问题缩小,调用自身。
调用栈可视化
当你调用 factorial(3) 时,栈的变化如下:

二、案例一:阶乘(factorial)
数学定义:
-
0! = 1
-
n! = n × (n-1)!
2.1 Python 实现
python
def factorial(n):
# 基准条件
if n == 0:
return 1
# 递归条件
return n * factorial(n - 1)
print(factorial(5)) # 输出 120
2.2 Java 实现
java
public class Factorial {
public static int factorial(int n) {
if (n == 0) return 1;
return n * factorial(n - 1);
}
public static void main(String[] args) {
System.out.println(factorial(5)); // 120
}
}
2.3 执行过程(n=3)
-
factorial(3)→ 3 ×factorial(2) -
factorial(2)→ 2 ×factorial(1) -
factorial(1)→ 1 ×factorial(0) -
factorial(0)→ 1 -
返回:1 ← 1×1 ← 2×1 ← 3×2 = 6
三、案例二:斐波那契数列
数学定义:
-
F(0) = 0, F(1) = 1
-
F(n) = F(n-1) + F(n-2)
3.1 朴素递归实现
python
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
print(fib(10)) # 55
3.2 调用树(n=5)

可以看到 fib(2) 被重复计算多次,导致指数级时间复杂度 O(2^n)。
四、递归优化:记忆化(Memoization)
用字典或数组缓存已经计算过的值,避免重复递归。
4.1 Python 记忆化
python
python
def fib_memo(n, memo={}):
if n in memo:
return memo[n]
if n <= 1:
return n
memo[n] = fib_memo(n-1, memo) + fib_memo(n-2, memo)
return memo[n]
print(fib_memo(50)) # 瞬间出结果
4.2 Java 使用数组缓存
python
java
public class Fibonacci {
private static long[] memo;
public static long fib(int n) {
if (n <= 1) return n;
if (memo[n] != 0) return memo[n];
memo[n] = fib(n-1) + fib(n-2);
return memo[n];
}
public static void main(String[] args) {
memo = new long[51];
System.out.println(fib(50));
}
}
优化后时间复杂度:O(n),空间复杂度 O(n)。
五、递归 vs 迭代(循环)

阶乘的迭代实现:
python
python
def factorial_iter(n):
result = 1
for i in range(1, n+1):
result *= i
return result
斐波那契的迭代实现:
python
python
def fib_iter(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
六、常见递归陷阱与解决方案

七、总结与思考
-
递归的本质:把大问题拆成同类型的小问题,直到可以直接解决。
-
何时使用递归:问题天然具有递归结构(如树遍历、汉诺塔、快速排序)。
-
何时避免递归:深度大、性能敏感、语言栈限制严(如 Python)。
递归就像俄罗斯套娃,最大的娃娃里装着稍小的,最小的不能再拆了,然后一个个打开,得到最终答案。
❓ 问题:你第一次理解递归时用的是什么例子?或者你在写递归时遇到过栈溢出吗?有没有什么妙招?欢迎在评论区分享,我会选出 3 位同学,送出《递归算法经典题目集锦》和《记忆化模板代码》。
📌 如果本文帮你打通了递归的任督二脉,请点 👍 赞 + 关注 ,本专栏 《大一突围》 持续输出编程基础与思维干货。
收藏本文,下次遇到递归题回来复习,画调用栈永远不过时。