LeeCode-二叉树递归专题

本文详细讲解了二叉树的前序、中序、后序遍历算法,并介绍了层次遍历和锯齿形层序遍历。通过代码示例和概念解析,帮助理解不同遍历方式的应用与核心区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉树的遍历

首先需要明确:前中后序是遍历二叉树过程中处理每一个节点的三个特殊时间点,绝不仅仅是三个顺序不同的 List:

  • 前序位置的代码在刚刚进入一个二叉树节点的时候执行;
  • 后序位置的代码在将要离开一个二叉树节点的时候执行;
  • 中序位置的代码在一个二叉树节点左子树都遍历完,即将开始遍历右子树的时候执行。

前中后序「位置」,就是常说的前中后序「遍历」有所区别:可以在前序位置写代码往一个 List 里面塞元素,那最后可以得到前序遍历结果;但并不是说你就不可以写更复杂的代码做更复杂的事。

二叉树遍历参考资料

简单对比“遍历方式”与“位置”的联系:

  • 前序遍历算法:
// 定义:输入一棵二叉树的根节点,返回这棵树的前序遍历结果
List<Integer> preorderTraverse(TreeNode root) {
    List<Integer> res = new LinkedList<>();
    if (root == null) {
        return res;
    }
    // 前序遍历的结果,root.val 在第一个
    res.add(root.val);
    // 利用函数定义,后面接着左子树的前序遍历结果
    res.addAll(preorderTraverse(root.left));
    // 利用函数定义,最后接着右子树的前序遍历结果
    res.addAll(preorderTraverse(root.right));
}
  • 中序遍历算法
List<Integer> preorderTraverse(TreeNode root) {
    List<Integer> res = new LinkedList<>();
    if (root == null) {
        return res;
    }
    res.addAll(preorderTraverse(root.left));
   // 中序遍历
    res.add(root.val);
    res.addAll(preorderTraverse(root.right));
}
  • 后续遍历算法
List<Integer> preorderTraverse(TreeNode root) {
    List<Integer> res = new LinkedList<>();
    if (root == null) {
        return res;
    }
    res.addAll(preorderTraverse(root.left));
    res.addAll(preorderTraverse(root.right));
    // 后序遍历
    res.add(root.val);
}
  • 二叉树的特殊遍历:层次遍历,层序遍历属于迭代遍历
// 输入一棵二叉树的根节点,层序遍历这棵二叉树
void levelTraverse(TreeNode root) {
    if (root == null) return;
    Queue<TreeNode> q = new LinkedList<>();
    q.offer(root);

    // 从上到下遍历二叉树的每一层
    while (!q.isEmpty()) {
        int sz = q.size();
        // 从左到右遍历每一层的每个节点
        for (int i = 0; i < sz; i++) {
            TreeNode cur = q.poll();
            // 将下一层节点放入队列
            if (cur.left != null) {
                q.offer(cur.left);
            }
            if (cur.right != null) {
                q.offer(cur.right);
            }
        }
    }
}

这里面 while 循环和 for 循环分别从上到下和从左到右的遍历:

遍历的几种常用方式

  • 递归
  • BFS
  • DFS

二叉树基础练习

144. 二叉树的前序遍历

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例 1:

输入:root = [1,null,2,3]
输出:[1,2,3]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

示例 4:

输入:root = [1,2]
输出:[1,2]

提示:

树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100

题解:前序遍历

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        self.queue = []
        self.prev(root)

        return self.queue


    def prev(self, node):
        if not node:
            return

        self.queue.append(node.val)
        self.prev(node.left)
        self.prev(node.right)

94. 二叉树的中序遍历

给定一个二叉树的根节点 root ,返回它的 中序 遍历。

题解:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        self.queue = []
        self.middle(root)

        return self.queue


    def middle(self, node):
        if not node:
            return
        self.middle(node.left)
        self.queue.append(node.val)
        self.middle(node.right)

145. 二叉树的后序遍历

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。

题解:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        self.queue = []
        self.post(root)

        return self.queue

    def post(self, node):
        if not node:
            return
        self.post(node.left)
        self.post(node.right)
        self.queue.append(node.val)

102. 二叉树的层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

题解:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        self.queue = []
        self.ans = []

        self.queue.append(root)
        self.ans.append([root.val])

        while self.queue:
            temp = []
            for _ in range(len(self.queue)):
                node = self.queue.pop(0)
                if node.left:
                    self.queue.append(node.left)
                    temp.append(node.left.val)
                if node.right:
                    self.queue.append(node.right)
                    temp.append(node.right.val)
            if temp:
                self.ans.append(temp)

        return self.ans

107. 二叉树的层序遍历 II

给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:[[15,7],[9,20],[3]]

示例 2:

输入:root = [1]
输出:[[1]]

示例 3:

输入:root = []
输出:[]

提示:

树中节点数目在范围 [0, 2000] 内
-1000 <= Node.val <= 1000

题解:对比层次遍历

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []

        self.queue = [root]
        self.ans = [[root.val]]

        while self.queue:
            temp = []
            for _ in range(len(self.queue)):
                node = self.queue.pop(0)
                if node.left:
                    self.queue.append(node.left)
                    temp.append(node.left.val)
                if node.right:
                    self.queue.append(node.right)
                    temp.append(node.right.val)

            if temp:
                self.ans.insert(0, temp)

        return self.ans

103. 二叉树的锯齿形层序遍历

给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[20,9],[15,7]]

示例 2:

输入:root = [1]
输出:[[1]]

示例 3:

输入:root = []
输出:[]

提示:

树中节点数目在范围 [0, 2000] 内
-100 <= Node.val <= 100

分析:锯齿层次遍历相对于层次遍历可以引入一个标志位来控制每层的遍历顺序即可

题解:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []

        self.queue = []
        self.ans = []
        self.flag = True

        self.queue.append(root)
        self.ans.append([root.val])

        while self.queue:
            temp = []
            self.flag = not self.flag
            
            for _ in range(len(self.queue)):
                node = self.queue.pop(0)
                if node.left:
                    temp.append(node.left.val)
                    self.queue.append(node.left)
                if node.right:
                    temp.append(node.right.val)
                    self.queue.append(node.right)
            
            if not self.flag:
                temp = temp[::-1]

            if temp:
                
                self.ans.append(temp)

        return self.ans

105. 从前序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例 2:

输入: preorder = [-1], inorder = [-1]
输出: [-1]

提示:

1 <= preorder.length <= 3000
inorder.length == preorder.length
-3000 <= preorder[i], inorder[i] <= 3000
preorder 和 inorder 均 无重复 元素
inorder 均出现在 preorder
preorder 保证 为二叉树的前序遍历序列
inorder 保证 为二叉树的中序遍历序列

题解:

-------------------------------------------------------------------------

104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:

给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回它的最大深度 3 。

题解:

  • 递归
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if root == None:
            return 0
        
        left = self.maxDepth(root.left)
        right = self.maxDepth(root.right)

        return max(left, right) + 1
  • BFS:仔细观察这里的BFS就是二叉树的层次遍历
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if root == None:
            return 0

        queue = []
        queue.append(root)
        ans = 0
        while queue:
            ans += 1
            for _ in range(len(queue)):
                node = queue.pop(0)
                if node.left:
                    queue.append(node.left)

                if node.right:
                    queue.append(node.right)
            
        return ans
  • DFS:DFS算法需要利用我们常说的遍历顺序:前序,中序,后序
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if root == None:
            return 0

        self.ans = 0
        self._dfs(root, 0)
        return self.ans

    def _dfs(self, node, level):
        if not node:
            return
        
        if self.ans < level + 1:
            self.ans = level + 1
        
        self._dfs(node.left, level + 1)
        self._dfs(node.right, level + 1)

总结:对于一个二叉树的遍历问题,一般都会有递归,广度优先搜索(BFS)和深度优先搜索(DFS)

543. 二叉树的直径

给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

示例 :

给定二叉树

          1
         / \
        2   3
       / \     
      4   5    
返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。

注意:两结点之间的路径长度是以它们之间边的数目表示。

题解:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def diameterOfBinaryTree(self, root: TreeNode) -> int:
        self.result = 0
        self.deep(root)
        return self.result
        
    def deep(self, root):
        if not root:
            return -1

        left = self.deep(root.left) + 1 if root.left else 0
        right = self.deep(root.right) + 1 if root.right else 0

        self.result = max(left + right, self.result)

        return max(left, right)
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

JackHCC

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值