在二叉树相关题目中总结出了,二叉树题目本质是“在递归中拆分问题,在回溯中合并结果”,答案往往产生于递的过程或归的过程。
一、什么是递归(结合二叉树理解)
递归 = 递 + 归
递(递进)
将原问题不断拆分为规模更小的子问题递的过程通常可以传递信息,更新答案……
在二叉树中,通常表现为:
“当前节点的问题 = 左子树的问题 + 右子树的问题”
归(回溯)
当到达边界条件(递归终点)后,逐层向上返回结果
在这个阶段,常常会:更新答案、将子树结果向上传递……
关键理解:
不要把递归想成“函数调用细节”,更多的关注树整体结构与子树的关系。
二、二叉树递归的正确思考顺序(非常重要)
推荐思考顺序
先想整体结构(递)
当前节点的问题能否拆成:左子树问题、右子树问题
在往下递的过程是否需要传递信息(可以后面用到的时候再补上)
再想递归终点(边界条件)
递的终点是什么?空节点怎么办?叶子节点怎么办?
最后想回溯时做什么(归)
返回什么值?是否需要更新答案?
结论:
二叉树递归,先“递”,再考虑“归”,而不是一开始就纠结细节。
三、答案一般出现在哪里?
二叉树题目的答案,通常出现在以下两个位置之一:
出现在「递的过程」
例如:
- 从根到叶路径
- 累加路径和
- 携带父节点信息向下传递
特点:
- 信息是自顶向下的
- 常通过参数传递或全局变量实现
出现在「归的过程」
- 例如:
- 最大深度
- 平衡二叉树
- 子树高度 / 子树和
特点:
- 信息是自底向上的
- 当前节点的结果依赖左右子树返回值
四、最小深度 vs 最大深度
这是一个非常容易写错的点,我在做题时思考了许久两者的区别。
最大深度(Max Depth)
逻辑非常自然:
- 左右子树谁深选谁
- 不存在歧义
1
maxDepth = max(leftDepth, rightDepth) + 1
最小深度(Min Depth)
关键区别点在于:非叶子节点
如果一个节点只有一个非空子节点, 最小深度只能来自非空的那一侧
常见错误
直接对左右子树取
min会错误地选择到
null的那一侧正确理解
空子树不能参与“最小路径”,路径问题重点一定是叶子节点,必须强制走到叶子节点
这也是为什么最小深度的代码逻辑比最大深度复杂
五、二叉树递归的通用解题模板
二叉树递归通常包含三个阶段
递(拆问题)
向左右子树递归调用
归(合结果)
利用左右子树返回值计算当前结果
记录答案
更新全局变量 或 返回当前节点的计算结果
很多题目其实只是这三个步骤的不同组合
六、父节点信息如何传递?
当「判断当前节点是否满足条件」需要父节点信息时,有两种常见方式:
方式一:递归参数向下传递
将父节点相关信息作为参数传入子递归,逻辑清晰
方式二:使用全局变量
实现简单
但要注意:重置问题
七、垂序遍历中的 Map 知识点整理
Map 按 key 排序
使用
TreeMap自动按 key 升序维护
集合自定义排序
使用
Comparator今天用在:List 排序
map.computeIfAbsent用法1
map.computeIfAbsent(key, k -> newValue);
含义是:
如果
key已存在 → 直接返回对应的value如果
key不存在 →使用函数计算一个
value放入 map
并返回该
value
在树遍历中非常常用
八、相关代码
本文涉及的所有代码与笔记,均已同步至我的 GitHub 算法仓库,作为 Java 后端校招过程中的学习记录。