树算法
一句话说明
树题本质上是在一棵分层结构里回答三件事:怎么遍历、怎么利用有序性质、怎么把子树答案合并起来。
先判断题目在问什么
flowchart TD A["树题"] --> B{"核心问题是什么?"} B -- "访问所有节点 / 输出顺序" --> C["遍历"] B -- "查找、插入、删除、有序性" --> D["BST"] B -- "路径、祖先、子树信息合并" --> E["递归 / 分治 / 树形 DP"] B -- "区间统计或动态前缀" --> F["线段树 / 树状数组"] B -- "字符串前缀匹配" --> G["Trie"]
最常用的选择表
| 题目特征 | 优先思路 | 为什么 |
|---|---|---|
| 需要复制树、序列化、先处理当前节点 | [[二叉树遍历/前序遍历 | 前序遍历]] |
| 需要拿到 BST 的有序序列 | [[二叉树遍历/中序遍历 | 中序遍历]] |
| 需要统计高度、节点数、平衡性、路径和 | [[二叉树遍历/后序遍历 | 后序遍历]] |
| 需要按层处理、求最小深度、右视图 | [[二叉树遍历/层序遍历 | 层序遍历]] |
| 题目强调左 < 根 < 右、有序查找 | [[BST操作/验证BST | BST 操作]] |
| 问最近公共祖先、路径信息 | [[经典问题/最近公共祖先 | LCA / 树上递归]] |
树和图有什么区别
复习时很容易混淆
树可以看成一种特殊的图,但它没有环,而且大多数题都会给你一个明确的根。正因为“没有环 + 有根”,递归才会在树题里这么自然。
flowchart LR A["图题思维"] --> B["visited 防环"] C["树题思维"] --> D["递归定义子问题"] C --> E["前中后序决定处理时机"]
📚 核心主题
1. 二叉树遍历
- 前序遍历:根 -> 左 -> 右,适合“先处理当前节点”
- 中序遍历:左 -> 根 -> 右,BST 中最关键
- 后序遍历:左 -> 右 -> 根,适合“子树先算完”
- 层序遍历:按层 BFS,适合最小深度、右视图、层统计
2. 二叉树基本操作
3. 二叉搜索树(BST)
4. 经典树题
5. 高级树结构
🧠 树题最常见的三种递归问法
| 类型 | 递归函数在回答什么 | 典型题 |
|---|---|---|
| 遍历型 | “走到这个节点时我要做什么?” | 前序、层序、路径打印 |
| 分治型 | “这棵子树的答案是什么?” | 高度、节点数、平衡树 |
| 约束型 | “这个节点允许处于什么范围 / 状态?” | 验证 BST、路径和、树形 DP |
一张图看前中后序
flowchart TD A["进入节点 root"] --> B["前序位置:先处理 root"] B --> C["递归左子树"] C --> D["中序位置:左边处理完后处理 root"] D --> E["递归右子树"] E --> F["后序位置:左右都处理完后处理 root"]
这个“处理时机”比“顺序名字”更重要
很多树题并不是让你真的输出遍历序列,而是让你把逻辑放在前序、中序或后序位置上。
建议学习顺序
易错点
树题里最常见的错误,是把“遍历顺序”和“递归时机”混为一谈。
- 前序 / 中序 / 后序,决定的是“当前节点什么时候处理”。
- 不是所有树题都要返回整棵树,很多题只需要子树返回一个值。
- 遇到 BST 时,要优先想到它的有序性质,不要按普通树处理。
- 如果题目问路径,先确认答案是“收集路径”还是“汇总子树信息”。
相关主题
返回:算法学习导航