返回
解开递归迷雾:通过二叉树力扣题掌握递归奥义
前端
2024-01-06 15:08:10
白话递归 2:深入浅出二叉树递归解题
在浩瀚的算法海洋中,递归始终是一颗闪亮的明星。它的独特魅力就在于:将一个复杂的问题分解成更小的子问题,并在解决子问题的过程中不断缩小问题的规模,最终实现问题的解决。对于二叉树这类层级结构的数据结构,递归更是大显身手,帮助我们轻松破解一道道难题。
本文将结合力扣题库中的二叉树相关题目,循序渐进地剖析递归算法的精髓,助力大家轻松掌握递归解题技巧。
走进递归的殿堂
递归的本质是分而治之:将一个复杂问题分解成更小的子问题,然后重复使用相同的解决方法解决子问题,直到问题被彻底解决。对于二叉树这类树形结构,递归的应用更是如鱼得水。
1. 前序遍历:根左右
前序遍历的顺序是:先访问根节点,然后递归访问左子树,最后递归访问右子树。
def preorder(root):
if root is None:
return
# 访问根节点
print(root.val)
# 递归访问左子树
preorder(root.left)
# 递归访问右子树
preorder(root.right)
2. 中序遍历:左根右
中序遍历的顺序是:先递归访问左子树,然后访问根节点,最后递归访问右子树。
def inorder(root):
if root is None:
return
# 递归访问左子树
inorder(root.left)
# 访问根节点
print(root.val)
# 递归访问右子树
inorder(root.right)
3. 后序遍历:左右根
后序遍历的顺序是:先递归访问左子树,然后递归访问右子树,最后访问根节点。
def postorder(root):
if root is None:
return
# 递归访问左子树
postorder(root.left)
# 递归访问右子树
postorder(root.right)
# 访问根节点
print(root.val)
4. 递归总结
通过以上几个例子的分析,我们可以总结出二叉树递归解题的一般步骤:
- 递归基线: 检查树是否为空,如果为空则返回。
- 分解子问题: 根据遍历顺序,将树分解成更小的子树。
- 递归调用: 对子树递归调用相同的函数。
- 组合结果: 将子树的递归结果组合成最终结果。
力扣实战演练
1. 二叉树的最大深度(104)
力扣 104 题考察了二叉树的最大深度,即从根节点到最深叶节点的最长路径的长度。我们可以用递归来解决:
def maxDepth(root):
if root is None:
return 0
# 计算左子树的最大深度
left_depth = maxDepth(root.left)
# 计算右子树的最大深度
right_depth = maxDepth(root.right)
# 返回左右子树最大深度中较大的那个加 1(根节点)
return max(left_depth, right_depth) + 1
2. 二叉树的路径和(112)
力扣 112 题要求找到所有从根节点到叶节点的路径,且这些路径上的所有数字之和等于给定的目标值。我们也可以用递归来解决:
def hasPathSum(root, targetSum):
if root is None:
return False
if root.left is None and root.right is None:
return root.val == targetSum
# 计算左子树的路径和
left_sum = hasPathSum(root.left, targetSum - root.val)
# 计算右子树的路径和
right_sum = hasPathSum(root.right, targetSum - root.val)
# 返回左右子树路径和中至少一个为 True
return left_sum or right_sum
结语
通过对二叉树力扣题目的分析,我们对递归算法有了更深入的理解。递归的思想在于分而治之,通过不断分解子问题,最终将复杂问题化解为简单的可解形式。掌握了递归算法,我们就能轻松应对更多数据结构和算法难题,在编程进阶的道路上不断前行。