17 - 递归:函数调用自己

3 阅读3分钟

想系统提升编程能力、查看更完整的学习路线,欢迎访问 AI Compass:github.com/tingaicompa… 仓库持续更新刷题题解、Python 基础和 AI 实战内容,适合想高效进阶的你。

17 - 递归:函数调用自己

学习目标: 理解递归的三要素和常见模式


📖 知识点讲解

递归就是函数调用自己。

递归三要素:

  1. 终止条件(base case): 什么时候停止递归
  2. 递归调用(recursive case): 如何分解问题
  3. 返回值: 如何组合子问题的结果

💻 代码示例

1. 基础递归

# 阶乘
def factorial(n):
    # 1. 终止条件
    if n == 0 or n == 1:
        return 1
    # 2. 递归调用
    return n * factorial(n - 1)

print(factorial(5))  # 120

# 斐波那契数列
def fib(n):
    if n <= 1:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(6))  # 8

# 求和
def sum_list(nums):
    if not nums:
        return 0
    return nums[0] + sum_list(nums[1:])

print(sum_list([1, 2, 3, 4, 5]))  # 15

2. 链表递归

# 反转链表(递归)
def reverseList(head):
    # 终止条件
    if not head or not head.next:
        return head

    # 递归反转后面的链表
    new_head = reverseList(head.next)

    # 反转当前节点
    head.next.next = head
    head.next = None

    return new_head

# 合并两个有序链表(递归)
def mergeTwoLists(l1, l2):
    if not l1:
        return l2
    if not l2:
        return l1

    if l1.val <= l2.val:
        l1.next = mergeTwoLists(l1.next, l2)
        return l1
    else:
        l2.next = mergeTwoLists(l1, l2.next)
        return l2

3. 树的递归

# 二叉树最大深度
def maxDepth(root):
    if not root:
        return 0
    return max(maxDepth(root.left), maxDepth(root.right)) + 1

# 翻转二叉树
def invertTree(root):
    if not root:
        return None
    root.left, root.right = root.right, root.left
    invertTree(root.left)
    invertTree(root.right)
    return root

# 对称二叉树
def isSymmetric(root):
    def isMirror(left, right):
        if not left and not right:
            return True
        if not left or not right:
            return False
        return (left.val == right.val and
                isMirror(left.left, right.right) and
                isMirror(left.right, right.left))

    return isMirror(root.left, root.right) if root else True

4. 回溯(递归的高级应用)

# 全排列
def permute(nums):
    result = []

    def backtrack(path, used):
        # 终止条件
        if len(path) == len(nums):
            result.append(path[:])
            return

        # 递归
        for i in range(len(nums)):
            if used[i]:
                continue

            # 选择
            path.append(nums[i])
            used[i] = True

            # 递归
            backtrack(path, used)

            # 撤销
            path.pop()
            used[i] = False

    backtrack([], [False] * len(nums))
    return result

# 组合总和
def combinationSum(candidates, target):
    result = []

    def backtrack(start, path, total):
        if total == target:
            result.append(path[:])
            return
        if total > target:
            return

        for i in range(start, len(candidates)):
            path.append(candidates[i])
            backtrack(i, path, total + candidates[i])
            path.pop()

    backtrack(0, [], 0)
    return result

🎯 递归可视化

factorial(3)
├── 3 * factorial(2)
│   ├── 2 * factorial(1)
│   │   └── 1
│   └── 2 * 1 = 2
└── 3 * 2 = 6

🏋️ 快速练习

练习:计算1到n的和

def sum_n(n):
    # 实现递归
    pass

print(sum_n(5))  # 15 (1+2+3+4+5)
点击查看答案
def sum_n(n):
    # 终止条件
    if n == 0:
        return 0
    # 递归调用
    return n + sum_n(n - 1)

print(sum_n(5))  # 15

🎓 小结

递归三要素: 终止条件、递归调用、返回值 ✅ 链表递归: 处理链表问题 ✅ 树的递归: 二叉树天然适合递归 ✅ 回溯: 递归+选择+撤销

注意: 递归可能导致栈溢出,深度过大时考虑迭代

下一步: 18-常见错误.md


如果这篇内容对你有帮助,推荐收藏 AI Compass:github.com/tingaicompa… 更多系统化题解、编程基础和 AI 学习资料都在这里,后续复习和拓展会更省时间。