Python:递归

一、递归的核心思想

递归(Recursion)​ 是一种通过 ​函数调用自身 来解决问题的编程技巧。它将一个大问题分解为更小的、结构相似的子问题,直到达到可以直接解决的简单情况(称为 ​基线条件)。

🌰 经典例子:计算阶乘
  • 问题:计算 n! = n × (n-1) × ... × 1
  • 递归思路
    def factorial(n):
        if n == 1:         # 基线条件
            return 1
        else:
            return n * factorial(n-1)  # 递推关系
  • 关键点n! 的问题被分解为计算 (n-1)!,直到 n=1 时直接返回结果。

二、递归的三要素

任何递归都必须包含以下三个部分,缺一不可:

1. ​基线条件(Base Case)​
  • 作用:终止递归的出口,防止无限循环。
  • 示例:在阶乘中,n == 1 时返回 1
2. ​递推关系(Recurrence Relation)​
  • 作用:将大问题转化为更小的同类问题。
  • 示例factorial(n) = n * factorial(n-1)
3. ​递归调用(Self Call)​
  • 作用:函数内部调用自身处理子问题。
  • 注意:每次调用必须向基线条件靠近。

三、递归的执行过程

理解递归的关键是 ​模拟调用栈(Call Stack)​ 的行为。每次递归调用会将当前状态压入栈,直到遇到基线条件后逐层返回。

🌰 以 factorial(3) 为例:
  1. 调用栈展开
    factorial(3)
    → 3 * factorial(2)
        → 2 * factorial(1)
            → 返回 1
        ← 2 * 1 = 2
    ← 3 * 2 = 6
  2. 最终结果6

四、递归的优缺点

✅ ​优点
  • 代码简洁:适合处理树形结构(如文件系统遍历、DOM树)。
  • 逻辑清晰:如分治算法(快速排序、归并排序)。
❌ ​缺点
  • 栈溢出风险:深度递归可能导致栈溢出(Stack Overflow)。
  • 重复计算:如斐波那契数列递归会重复计算子问题。
🛠️ ​优化方法
  • 尾递归优化:某些编译器能优化尾递归(如函数最后一步是递归调用)。
  • 记忆化(Memoization)​:缓存已计算的结果(如用装饰器 @lru_cache)。

五、递归 vs 迭代

递归迭代
依赖函数调用自身使用循环结构
代码简洁但可能低效通常效率更高
适合分治问题适合简单重复问题
🌰 斐波那契数列对比
# 递归(低效,O(2^n))
def fib(n):
    if n <= 1:
        return n
    return fib(n-1) + fib(n-2)

# 迭代(高效,O(n))
def fib_iter(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a

六、递归的典型应用场景

  1. 树/图遍历:如二叉树的先序、中序、后序遍历。
  2. 回溯算法:如八皇后问题、数独求解。
  3. 分治算法:如归并排序、快速排序。
  4. 动态规划:如背包问题(需结合记忆化)。

七、如何写出正确的递归?

  1. 明确基线条件:确保递归最终能终止。
  2. 缩小问题规模:每次递归必须更接近基线条件。
  3. 假设子问题已解决:相信递归能正确处理更小的问题(类似数学归纳法)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愚戏师

缘分啊,道友

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值