递归表达式必须包含明确的基例和递归体,用更小规模的同类子问题描述原问题,如阶乘n!=n×(n−1)!,需确保参数收敛、类型一致且与基例自洽。

函数表达式定义递归逻辑,关键在于**明确递归出口(基例)和递归体(调用自身的表达式)**,二者缺一不可。它不是单纯“写个 self-call”,而是用数学或逻辑关系把原问题拆解为更小的同类子问题,并确保每次调用都向出口靠近。
递归表达式必须包含两个核心成分
一个有效的递归表达式,本质是把函数当前行为用“自身在更小规模上的结果”来描述。例如阶乘:
n! = n × (n−1)!
这个等式就是递归表达式——它没直接算出结果,而是指出:要算 n 的阶乘,先算 n−1 的阶乘,再乘以 n。
- 它隐含了规模缩小:(n−1)! 比 n! 规模小 1
- 它依赖基例终止:当 n=0 时,定义 0!=1,不再展开
- 它保持问题类型一致:左边是阶乘,右边仍是阶乘,只是参数变小
写递归表达式时常见错误
很多初学者写出的“递归”实际是无效循环或逻辑断裂,典型问题包括:
-
缺少或错设基例:比如写
if n == 1: return 1,但输入可能是 0 或负数,导致无限调用 -
参数未真正缩小:如用
func(n)而不是func(n-1),或缩小方式不收敛(如n//2但没处理奇偶边界) -
表达式与基例不自洽:比如定义斐波那契时写
f(n) = f(n-1) + f(n-2),但基例只设f(0)=0,漏了f(1)=1,会导致 f(2) 计算错误
从问题描述直接推导递归表达式
不必凭空构造,可按三步走:
-
观察最小可解情形:比如字符串反转,空串或单字符就是结果本身 → 基例:
if len(s) ≤ 1: return s -
拆解一步操作:拿掉首字符,剩下部分递归反转,再把首字符拼到末尾 → 表达式:
reverse(s[1:]) + s[0] -
验证规模收敛性:每次调用
s[1:]长度减 1,终将触达基例
无返回值函数的递归表达式也存在
即使不返回值,递归逻辑仍体现为“当前动作 + 对子问题的相同动作”。例如倒计时:
- 基例:
if start - 表达式:
print(start); count_down(start - 1) - 这里“表达式”是语句序列,而非数学等式,但逻辑结构一致:先处理当前层(打印),再交由更小规模子问题处理剩余部分











