第一部分:核心概念与理论(笔试重点)
这部分是理解递归的基础,主要应对笔试中的概念题和简答题。
1. 什么是递归?
递归是一种解决问题的强大思想,它的核心是“自己调用自己”。
- 官方定义:如果一个对象部分地包含自身,或利用自身来定义自身,则称这个对象是递归的。如果一个过程(或函数)直接或间接地调用自身,则称这个过程是递归过程。
- 故事理解:就像课件里讲的那个故事:“从前有座山,山上有座庙,庙里有个老和尚在给小和尚讲故事,故事是‘从前有座山…’” 这个故事的结构就是递归的。
- 数学理解:自然数的定义也是递归的。
- 1 是自然数。
- 如果 nnn 是自然数,那么 n+1n+1n+1 也是自然数。
2. 递归的两个基本要素
任何一个有效的递归算法,都必须包含两个部分,缺一不可:
- 递归描述(Recursive Step):将原始问题分解为一个或多个规模更小、但结构相同的子问题。这是“递”的过程。例如,想求
n!,可以先去求(n-1)!。 - 递归出口(Base Case / Termination Condition):一个或多个可以直接求解的最小问题。当问题规模缩小到这个程度时,不再进行递归调用,而是直接返回结果。这是“归”的起点,也是防止无限循环的关键。例如,
0!的值是1,这就是出口。
简答题考点:若缺少递归出口,会导致函数无限调用自身,直到程序运行栈的内存被耗尽,引发“栈溢出”(Stack Overflow)错误。
3. 递归是如何工作的?—— 函数调用栈
计算机通过一种叫做“栈(Stack)”的数据结构来实现递归。每当一个函数被调用时,系统会做以下事情(进层/递推):
- 保存现场:将当前函数的参数、局部变量、返回地址等信息压入栈中,形成一个“活动记录”(或称“栈帧”)。
- 参数传递:为被调用的新函数(即递归的下一层)分配空间,并传递参数。
- 跳转执行:程序控制权转移到被调用函数的入口。
当递归到达出口,函数执行完毕准备返回时,系统会(退层/回归):
- 保存结果:保存本次计算的返回值。
- 恢复现场:从栈顶弹出当前的活动记录,释放空间,并恢复上一层函数的参数和局部变量。
- 跳转返回:依照之前保存的返回地址,将程序控制权和返回值交还给上一层调用者。
这个先“递推”再“回归”的过程,完美地体现了递归“先深入、再返回”的执行特性。
4. 递归与迭代(循环)的对比
| 特性 | 递归 (Recursion) | 迭代 (Iteration / Loop) |
|---|---|---|
| 代码 | 通常更简洁、易于理解,更贴近问题的数学定义。 | 代码通常更长,但逻辑可能更直接。 |
| 性能 | 函数调用和返回有额外开销(压栈、弹栈),速度较慢,占用内存较多。 | 没有函数调用开销,速度快,内存占用恒定。 |
| 风险 | 递归层次太深可能导致栈溢出。 | 比较安全,不会有栈溢出的问题。 |
| 转换 | 所有递归都可以用迭代(通常借助栈)实现,但转换可能很复杂。 | 迭代转换为递归通常比较容易。 |
第二部分:经典问题与算法(笔试 & 机试重点)
这部分是考试的重中之重,要求不仅能理解,还要能徒手写出代码。
1. 阶乘 (Factorial)
-
问题描述:计算非负整数 nnn 的阶乘 n =n×(n−1)×⋯×1n\! = n \times (n-1) \times \dots \times 1n=n×(n−1)×⋯×1。
-
递归逻辑:
- 递归描述:n =n×(n−1) n\! = n \times (n-1)\!n=n×(n−1) (对于 n 0n\>0n0)。
- 递归出口:0 =10\! = 10=1。
-
代码实现:
C++
long long factorial(int n) { // 递归出口 (Base Case) if (n == 0) { return 1; } // 递归描述 (Recursive Step) else { return n * factorial(n - 1); } }Python
def factorial(n): # 递归出口 (Base Case) if n == 0: return 1 # 递归描述 (Recursive Step) else: return n * factorial(n - 1)

最低0.47元/天 解锁文章
2209

被折叠的 条评论
为什么被折叠?



