1. 二叉树基础概念与LeetCode高频考点解析
二叉树是每个程序员必须掌握的基础数据结构,尤其在LeetCode算法面试中出现的频率极高。作为树形结构的典型代表,二叉树由节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。这种结构天然适合递归处理,这也是为什么二叉树问题在算法面试中如此受青睐。
在LeetCode Hot 100题目中,二叉树相关题目占比超过15%,主要考察以下几个核心方向:遍历算法(前序、中序、后序、层序)、构建问题(根据遍历结果重建二叉树)、属性判断(对称性、平衡性、相同树等)以及路径相关问题。掌握这些题型,就能解决80%以上的二叉树面试题。
二叉树问题的解决往往遵循"定义子问题→处理当前节点→递归处理子树"的模式。这种分治思想是理解二叉树算法的钥匙。
2. 二叉树遍历算法精讲
2.1 递归遍历模板
递归是最直观的遍历方式,代码简洁但需要注意栈溢出风险。以下是三种递归遍历的统一模板:
python复制def traverse(root):
if not root: return
# 前序位置
traverse(root.left)
# 中序位置
traverse(root.right)
# 后序位置
不同遍历顺序的区别仅在于处理当前节点的时机:
- 前序:在处理子节点前访问(根→左→右)
- 中序:在处理左子节点后、右子节点前访问(左→根→右)
- 后序:在处理完子节点后访问(左→右→根)
2.2 迭代遍历实现
面试官常要求用迭代实现遍历,这需要显式使用栈来模拟递归。以前序遍历为例:
python复制def preorderTraversal(root):
stack, res = [root], []
while stack:
node = stack.pop()
if node:
res.append(node.val)
stack.append(node.right) # 右先入栈后处理
stack.append(node.left)
return res
层序遍历(BFS)则需要使用队列:
python复制from collections import deque
def levelOrder(root):
q, res = deque([root]), []
while q:
level = []
for _ in range(len(q)):
node = q.popleft()
if node:
level.append(node.val)
q.append(node.left)
q.append(node.right)
if level: res.append(level)
return res
3. 高频题型解题套路
3.1 二叉树构造问题
LeetCode经典题目如105(前序+中序构造二叉树)、106(中序+后序构造二叉树)等,解题关键在于:
- 前序/后序确定根节点位置
- 中序划分左右子树
- 递归构建子树
示例代码(前序+中序构建):
python复制def buildTree(preorder, inorder):
if not preorder: return None
root_val = preorder[0]
root = TreeNode(root_val)
idx = inorder.index(root_val)
root.left = buildTree(preorder[1:idx+1], inorder[:idx])
root.right = buildTree(preorder[idx+1:], inorder[idx+1:])
return root
3.2 二叉树属性判断
常见题型包括:
- 对称二叉树(LeetCode 101):比较左右子树镜像
- 平衡二叉树(LeetCode 110):递归检查高度差
- 相同树(LeetCode 100):同步遍历比较节点
以对称二叉树为例:
python复制def isSymmetric(root):
def compare(left, right):
if not left and not right: return True
if not left or not right: return False
return (left.val == right.val and
compare(left.left, right.right) and
compare(left.right, right.left))
return compare(root.left, root.right) if root else True
4. 进阶技巧与优化策略
4.1 Morris遍历
一种空间复杂度O(1)的遍历方法,通过修改树结构实现:
python复制def morrisInorder(root):
curr = root
while curr:
if not curr.left:
print(curr.val)
curr = curr.right
else:
# 找前驱节点
pre = curr.left
while pre.right and pre.right != curr:
pre = pre.right
if not pre.right:
pre.right = curr # 建立线索
curr = curr.left
else:
pre.right = None # 拆除线索
print(curr.val)
curr = curr.right
4.2 路径问题处理
典型题目如124(二叉树最大路径和)、112(路径总和)等。处理路径问题时需要注意:
- 路径不一定经过根节点
- 可能需要同时考虑向上返回的值和全局最大值
最大路径和解决方案:
python复制def maxPathSum(root):
max_sum = -float('inf')
def dfs(node):
nonlocal max_sum
if not node: return 0
left = max(dfs(node.left), 0)
right = max(dfs(node.right), 0)
max_sum = max(max_sum, left + right + node.val)
return max(left, right) + node.val
dfs(root)
return max_sum
5. 常见错误与调试技巧
- 空指针问题:始终检查节点是否为null,特别是在处理子树时
- 递归终止条件缺失:导致无限递归和栈溢出
- 修改了原始结构:如Morris遍历后未恢复树结构
- 全局变量未重置:在多次调用函数时出现值污染
调试建议:
- 对小规模用例画图分析执行流程
- 打印递归深度和关键变量值
- 使用LeetCode可视化工具观察树结构
在面试中,建议先明确问题边界条件(如空树、单节点等),再给出解决方案。解释清楚时间/空间复杂度往往比直接写代码更重要。
