尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

二叉树算法精讲:从基础到面试高频题解析

二叉树算法精讲:从基础到面试高频题解析 1. 二叉树基础与代码随想录训练营Day14解析今天咱们聊聊算法训练中绕不开的经典数据结构——二叉树。在代码随想录算法训练营的Day14课程中二叉树作为核心内容被重点讲解。这个看似简单的数据结构在实际算法面试中出现的频率高达70%以上是每个程序员必须啃下的硬骨头。我参加过多次大厂技术面试发现面试官特别钟爱用二叉树问题考察候选人的递归思维和分治能力。比如去年我在面试中就遇到过一道二叉树层序遍历的变种题要求同时输出每层的最大值和最小值。当时如果没有扎实的二叉树基础很可能就会在现场卡壳。2. 二叉树核心概念与实现2.1 二叉树的基本结构二叉树每个节点最多有两个子节点通常称为左孩子和右孩子。用代码表示一个二叉树节点最基本的结构是这样的class TreeNode: def __init__(self, val0, leftNone, rightNone): self.val val self.left left self.right right在实际应用中二叉树有多种特殊形式满二叉树每个节点都有0或2个子节点完全二叉树除了最后一层其他层都完全填满二叉搜索树(BST)左子树所有节点值小于根节点右子树所有节点值大于根节点注意二叉搜索树的中序遍历结果是一个有序序列这个特性经常被用来验证BST的正确性。2.2 二叉树的创建与遍历创建二叉树通常有两种方式手动构建节点并连接通过数组序列化如LeetCode常用的表示法以数组[3,9,20,null,null,15,7]为例对应的二叉树是3 / \ 9 20 / \ 15 7二叉树的遍历方式主要有四种前序遍历根→左→右中序遍历左→根→右后序遍历左→右→根层序遍历按层次从上到下从左到右递归实现前序遍历的代码示例def preorder(root): if not root: return [] return [root.val] preorder(root.left) preorder(root.right)3. 二叉树常见算法问题解析3.1 深度优先搜索(DFS)应用DFS是解决二叉树问题的利器。比如求二叉树的最大深度def maxDepth(root): if not root: return 0 return 1 max(maxDepth(root.left), maxDepth(root.right))另一个经典问题是路径总和def hasPathSum(root, targetSum): if not root: return False if not root.left and not root.right: return root.val targetSum return hasPathSum(root.left, targetSum-root.val) or hasPathSum(root.right, targetSum-root.val)3.2 广度优先搜索(BFS)应用BFS适合处理层序遍历相关问题。比如锯齿形层序遍历def zigzagLevelOrder(root): if not root: return [] queue [root] res [] level 0 while queue: size len(queue) temp [] for _ in range(size): node queue.pop(0) temp.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) if level % 2 1: temp.reverse() res.append(temp) level 1 return res4. 二叉树进阶问题与优化4.1 二叉树的构造问题根据遍历结果重建二叉树是常见难题。比如从前序和中序遍历构造二叉树def buildTree(preorder, inorder): if not preorder or not inorder: return None root_val preorder[0] root TreeNode(root_val) idx inorder.index(root_val) root.left buildTree(preorder[1:idx1], inorder[:idx]) root.right buildTree(preorder[idx1:], inorder[idx1:]) return root4.2 二叉搜索树的操作BST的搜索、插入和删除操作都有特定规律。比如删除BST中的节点def deleteNode(root, key): if not root: return None if key root.val: root.left deleteNode(root.left, key) elif key root.val: root.right deleteNode(root.right, key) else: if not root.left: return root.right if not root.right: return root.left min_node findMin(root.right) root.val min_node.val root.right deleteNode(root.right, min_node.val) return root def findMin(node): while node.left: node node.left return node5. 二叉树问题实战技巧5.1 递归与迭代的选择递归代码简洁但可能有栈溢出风险迭代更可控但代码复杂。对于简单问题优先用递归复杂或深度大的树考虑迭代。递归转迭代的通用方法是使用栈模拟调用过程。以前序遍历为例def preorderIterative(root): if not root: return [] stack [root] res [] while stack: node stack.pop() res.append(node.val) if node.right: stack.append(node.right) if node.left: stack.append(node.left) return res5.2 常见错误与调试技巧新手常犯的错误包括忘记处理空节点导致NullPointerException递归终止条件不正确导致无限循环混淆遍历顺序导致错误结果调试二叉树问题时可以打印树的结构辅助理解使用小规模的测试用例在递归函数中加入打印语句跟踪执行流程6. 代码随想录训练营Day14重点解析代码随想录Day14课程通常涵盖以下核心内容二叉树理论基础递归遍历的实现迭代遍历的实现统一风格的迭代法二叉树层序遍历及应用特别值得注意的是层序遍历的模板代码可以解决很多相关问题def levelOrder(root): if not root: return [] queue [root] res [] while queue: level_size len(queue) level [] for _ in range(level_size): node queue.pop(0) level.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) res.append(level) return res这个模板稍加修改就能解决诸如右视图、左视图、锯齿形遍历、每层最大值等问题。7. 二叉树问题的高频面试题根据我的面试经验以下二叉树问题出现频率最高二叉树的最大深度Easy验证二叉搜索树Medium二叉树的最近公共祖先Medium二叉树中的最大路径和Hard序列化和反序列化二叉树Hard以最近公共祖先(LCA)问题为例递归解法非常优雅def lowestCommonAncestor(root, p, q): if not root or root p or root q: return root left lowestCommonAncestor(root.left, p, q) right lowestCommonAncestor(root.right, p, q) if left and right: return root return left if left else right8. 学习建议与资源推荐掌握二叉树需要大量练习。我的建议是先理解基本概念和遍历方式从简单递归问题入手如深度、对称判断逐步过渡到构造、修改类问题最后攻克复杂问题如序列化、最大路径和推荐练习平台LeetCode二叉树专题约150题代码随想录二叉树章节《剑指Offer》二叉树相关题目在实际面试中二叉树问题往往不是考察你能不能写出代码而是看你解决问题的思路是否清晰代码是否健壮处理边界条件以及能否分析时间空间复杂度。
返回列表