直接回答:尾递归是指递归调用是函数的最后一步操作、返回值不再参与任何计算的递归形式。阶乘的朴素递归 n * fact(n-1) 中乘法发生在递归返回之后,不是尾递归;引入累加器参数把中间积一路传下去,即可写成尾递归版本。

展开解析:尾递归的优势在于尾调用优化(TCO):由于递归返回后无事可做,当前栈帧可以直接复用给下一层调用,递归在机器层面等价于循环,空间复杂度从 O(n) 降到 O(1),不会栈溢出。支持该优化的有 Scheme(规范强制)、Erlang/Elixir、Scala(@tailrec)、Kotlin(tailrec)等;而 CPython、Java 不做 TCO,尾递归只是写法上更接近迭代。因此回答时最好点明:优势是否兑现取决于语言实现,不能笼统说"尾递归省栈"。追问方向:如何把任意递归改写成尾递归(累加器、CPS)、为什么很多语言拒绝实现 TCO(破坏栈回溯信息、调试困难)。

示例

(define (fact n)
  (define (iter n acc)
    (if (<= n 1)
        acc
        (iter (- n 1) (* n acc)))) ; 最后一步是递归调用本身
  (iter n 1))