
一起动脑筋 · 先看一个小故事
机器人不断说“请下一位来帮忙”,却没有任何一位真正完成最小任务。这条队伍就停不下来。
把过程摊开来看
- 任务 n = 2交给 n = 1
- 任务 n = 1交给 n = 0
- 终止条件n = 0 直接回答
- 返回不再新增任务
终止条件让最小情况直接得到答案,而不继续递归。
还要检查每一次调用是否真的朝它靠近。写了 n == 0,却每次 n 加 1,仍然可能永远到不了。
01什么是停止条件?
递归里更准确的说法通常是基本情况(base case):
if (n == 0) {
return;
}
它告诉函数:“到这里已经不用再拆了,可以直接结束。”
02只有停止条件就够了吗?
不够。
void f(int n) {
if (n == 0) {
return;
}
f(n + 1); // 越走越远
}
如果从 f(3) 开始,n 会变成 4、5、6……根本到不了 0。
03正确递归需要两件事
有终点
存在可以直接结束的基本情况。
朝终点前进
每次递归都让问题更接近基本情况。
04如果没有终止,会发生什么?
f(5)f(4)f(3)f(2)...
活跃调用不断增加,占用的调用状态越来越多。
实际系统的调用栈空间有限,最终常见结果是栈溢出或程序异常终止。
05停止条件一定写成 n == 0 吗?
当然不是。
if (left > right) {
return;
}
或者:
if (node == nullptr) {
return;
}
基本情况取决于问题本身。
06怎样检查递归会不会停?
可以问三个问题:
终点是什么?
什么情况不再递归?
每层变了什么?
问题规模是否更小?
一定能到吗?
所有合法输入都会最终到达吗?
你已经知道了什么
- 递归需要基本情况来停止继续调用。
- 只有基本情况还不够,递归过程还必须向它靠近。
- 无限递归会不断增加活跃调用。
- 调用层数过深可能导致栈溢出。
- 基本情况的形式由具体问题决定。
下一篇:递归时调用栈发生了什么?
轮到你来试一试
规则是 n == 0 停止,每次 n 减 2;从 3 开始会碰到 0 吗?
想好了吗?点开看解释
不会,序列是 3、1、-1……应重新设计递减规则或终止条件,并明确输入范围。