1. 二叉树面试核心知识点全解析
作为Java开发者面试中的必考知识点,二叉树相关题目在中低难度面试题中占比超过80%。掌握好这部分内容,能让你在技术面试中游刃有余。下面我将从五个维度全面剖析二叉树的核心考点。
1.1 二叉树的结构定义与实现
在面试中,手写二叉树节点定义是最基础的考察点。力扣、牛客等平台的二叉树节点定义都是固定的Java版本,必须烂熟于心:
java复制public class TreeNode {
int val;
TreeNode left;
TreeNode right;
// 三种构造方法,面试手写可只写前两种
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
面试技巧:
- 手写时不需要写注释,但构造方法要完整
- 如果时间紧张,可以只写前两种构造方法(覆盖90%的使用场景)
- 注意变量命名规范,使用left/right而不是lChild/rChild等非标准命名
1.2 二叉树的五大核心分类
面试中常会问到不同类型的二叉树及其特性,以下是必须掌握的五大类型:
| 类型 | 核心定义 | 面试考点 | 典型问题 |
|---|---|---|---|
| 普通二叉树 | 每个节点最多2个子节点,无其他限制 | 基础遍历、深度计算、对称判断 | 前中后序遍历、最大深度 |
| 满二叉树 | 除叶子节点外都有左右子节点,且叶子在同一层 | 节点数计算(2^h-1) | 计算满二叉树的节点数 |
| 完全二叉树 | 层序遍历编号与满二叉树一致 | 数组转二叉树、堆结构 | 堆的实现、完全二叉树验证 |
| 二叉搜索树(BST) | 左子树所有节点值 < 根 < 右子树所有节点值 | 中序遍历升序、搜索效率 | BST验证、第K小元素 |
| 平衡二叉树(AVL) | 左右子树高度差≤1 | 平衡性维护、旋转操作 | AVL树旋转、红黑树基础 |
常见误区:
- 混淆完全二叉树和满二叉树的概念
- 认为BST的中序遍历可以有重复值(实际必须是严格升序)
- 忽略平衡二叉树的高度差绝对值≤1的条件
1.3 二叉树的四大遍历方式
遍历是二叉树所有操作的基础,必须掌握递归和迭代两种实现方式。
1.3.1 深度优先遍历(DFS)
递归模板(必须熟记):
java复制// 前序遍历
void preorder(TreeNode root) {
if(root == null) return;
System.out.print(root.val + " "); // 访问根节点
preorder(root.left); // 左子树
preorder(root.right); // 右子树
}
// 中序遍历
void inorder(TreeNode root) {
if(root == null) return;
inorder(root.left); // 左子树
System.out.print(root.val + " "); // 访问根节点
inorder(root.right); // 右子树
}
// 后序遍历
void postorder(TreeNode root) {
if(root == null) return;
postorder(root.left); // 左子树
postorder(root.right); // 右子树
System.out.print(root.val + " "); // 访问根节点
}
迭代实现关键点:
- 前序:用栈,顺序为根→右→左(栈先进后出)
- 中序:先压入所有左节点,再处理右节点
- 后序:可以改造前序(根→右→左)然后反转结果
1.3.2 广度优先遍历(BFS)
层序遍历是BFS的典型应用,使用队列实现:
java复制void levelOrder(TreeNode root) {
if(root == null) return;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()) {
int size = queue.size(); // 当前层的节点数
for(int i=0; i<size; i++) {
TreeNode node = queue.poll();
System.out.print(node.val + " ");
if(node.left != null) queue.offer(node.left);
if(node.right != null) queue.offer(node.right);
}
System.out.println(); // 换行表示新的一层
}
}
面试技巧:
- 递归写法虽然简洁,但要警惕栈溢出风险(树很深时)
- 迭代写法通常更安全,也是面试官喜欢追问的点
- 层序遍历中记录每层节点数是关键技巧
1.4 二叉树基础操作全解
基于遍历可以延伸出各种基础操作,以下是面试中最常考的8类操作:
-
求最大深度
- 递归:1 + max(左深度, 右深度)
- 迭代:层序遍历的层数
-
求最小深度
- 递归:只有到叶子节点才计算深度
- 迭代:层序遍历遇到的第一个叶子节点
-
判断对称二叉树
- 递归:比较左左和右右、左右和右左
- 迭代:使用队列成对比较节点
-
求节点总数
- 递归:1 + 左节点数 + 右节点数
- 迭代:遍历计数
-
求叶子节点数
- 递归:左右都为空时计数+1
- 迭代:遍历检查左右子节点
-
验证二叉搜索树
- 方法1:中序遍历检查是否升序
- 方法2:递归检查值范围
-
最近公共祖先
- 递归:找到p/q就返回,左右都找到则当前是祖先
- 迭代:记录父节点路径
-
二叉树的直径
- 递归:计算每个节点的左右深度和
- 全局变量记录最大值
1.5 二叉树核心特性总结
- BST的中序遍历结果是严格升序,这是验证BST和搜索的核心
- 完全二叉树的节点位置可以数组表示,是堆的基础
- 对称二叉树的镜像遍历结果相同
- 深度与高度:深度是根到节点的距离,高度是节点到叶子的距离(面试中常混用,需确认定义)
2. 高频面试题精讲
下面通过4道经典题目,深入解析二叉树的面试考点。
2.1 前序遍历(LeetCode 144)
题目:给定二叉树根节点,返回前序遍历结果。
递归解法:
java复制class Solution {
List<Integer> res = new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root == null) return res;
res.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return res;
}
}
迭代解法:
java复制class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if(root == null) return res;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()) {
TreeNode node = stack.pop();
res.add(node.val);
if(node.right != null) stack.push(node.right);
if(node.left != null) stack.push(node.left);
}
return res;
}
}
面试注意点:
- 递归终止条件不能遗漏
- 迭代法压栈顺序是先右后左
- 可以提及统一迭代法(标记法)作为扩展
2.2 二叉树的最大深度(LeetCode 104)
题目:求二叉树的最大深度。
递归解法:
java复制class Solution {
public int maxDepth(TreeNode root) {
if(root == null) return 0;
return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
}
}
迭代解法:
java复制class Solution {
public int maxDepth(TreeNode root) {
if(root == null) return 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int depth = 0;
while(!queue.isEmpty()) {
int size = queue.size();
for(int i=0; i<size; i++) {
TreeNode node = queue.poll();
if(node.left != null) queue.offer(node.left);
if(node.right != null) queue.offer(node.right);
}
depth++;
}
return depth;
}
}
常见变种:
- 最小深度(注意只有到叶子节点才计算)
- 平衡二叉树判断(每个节点的左右子树高度差≤1)
2.3 对称二叉树(LeetCode 101)
题目:判断二叉树是否镜像对称。
递归解法:
java复制class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null) return true;
return check(root.left, root.right);
}
private boolean check(TreeNode left, TreeNode right) {
if(left == null && right == null) return true;
if(left == null || right == null) return false;
return left.val == right.val
&& check(left.left, right.right)
&& check(left.right, right.left);
}
}
迭代解法:
java复制class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null) return true;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root.left);
queue.offer(root.right);
while(!queue.isEmpty()) {
TreeNode n1 = queue.poll();
TreeNode n2 = queue.poll();
if(n1 == null && n2 == null) continue;
if(n1 == null || n2 == null || n1.val != n2.val) return false;
queue.offer(n1.left);
queue.offer(n2.right);
queue.offer(n1.right);
queue.offer(n2.left);
}
return true;
}
}
易错点:
- 只比较值相等而忽略结构对称
- 迭代法需要成对入队和出队节点
2.4 验证二叉搜索树(LeetCode 98)
题目:验证给定二叉树是否是有效的BST。
中序遍历解法:
java复制class Solution {
long pre = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
if(root == null) return true;
if(!isValidBST(root.left)) return false;
if(root.val <= pre) return false;
pre = root.val;
return isValidBST(root.right);
}
}
递归范围解法:
java复制class Solution {
public boolean isValidBST(TreeNode root) {
return check(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
private boolean check(TreeNode node, long min, long max) {
if(node == null) return true;
if(node.val <= min || node.val >= max) return false;
return check(node.left, min, node.val)
&& check(node.right, node.val, max);
}
}
关键点:
- 使用long避免Integer.MIN_VALUE边界问题
- BST要求严格递增(不能有相等值)
- 递归范围解法效率更高
3. 面试实战技巧
3.1 解题思路框架
二叉树问题的解题思路通常遵循以下模式:
- 确定遍历方式:根据问题特点选择前序、中序、后序或层序
- 递归思路:明确递归终止条件和递归过程
- 迭代实现:用栈或队列模拟递归过程
- 边界处理:考虑空树、单节点等特殊情况
- 复杂度分析:时间O(n),空间O(h)或O(n)
3.2 面试应答策略
- 先写递归解法:通常更简洁直观
- 主动解释思路:说明选择这种解法的原因
- 讨论边界条件:展示全面思考
- 准备迭代实现:应对面试官追问
- 分析复杂度:体现算法素养
3.3 常见问题准备
- 递归和迭代的优缺点比较
- 各种遍历方式的应用场景
- BST的特性及操作复杂度
- 完全二叉树与堆的关系
- 二叉树序列化与反序列化
4. 扩展学习建议
掌握了上述内容后,可以进一步学习:
-
进阶算法:
- 二叉树序列化/反序列化
- BST的插入、删除操作
- 二叉树的Morris遍历
- 红黑树基本原理
-
相关数据结构:
- 堆的实现与应用
- Trie树(前缀树)
- 线段树与树状数组
-
刷题推荐:
- 二叉树的所有路径(LeetCode 257)
- 路径总和系列(LeetCode 112/113/437)
- 二叉树的右视图(LeetCode 199)
- 二叉树的锯齿形层序遍历(LeetCode 103)
记住,二叉树相关问题的核心是理解遍历方式和递归思想。多练习、多总结,在面试中遇到二叉树问题时就能从容应对了。