§1
题目描述
判断一棵树是否高度平衡:任意节点左右子树高度差不超过 1。
root = [3,9,20,null,null,15,7]
输出 = true
§2
思路解析动画文字版
关键不是背模板,而是看懂为什么这题适合二叉树 · 后序。
1. 后序自底向上算高度:判断是否平衡:每个节点的左右子树高度差都要 ≤ 1。用后序遍历自底向上算高度,顺手查平衡。
2. 叶子高度 = 1:先到最底层:叶子 9、15、7 的高度都是 1。
3. 节点 20 · 平衡,高度 2:节点 20:左(15)高 1、右(7)高 1,差 |1−1|=0 ≤ 1 平衡 → 高度 = 1+max(1,1) = 2。
4. 根 3 · 平衡,高度 3:根 3:左(9)高 1、右(20)高 2,差 |1−2|=1 ≤ 1 平衡 → 高度 3。
5. 关键帧 · -1 短路:关键帧:后序让每个节点一次算高度 + 顺手查平衡。一旦某子树不平衡就返回 -1 短路,父节点见到 -1 直接也返 -1,不重复算高度 → O(n)。根没返 -1 → 整树平衡 (true)。
6. 反例 · 不平衡:反例:这棵树根 1 的左子树高 2、右子树高 0,差 |2−0|=2 > 1 → 不平衡,height 返回 -1 一路短路到根 → false。
把这句话记住,下次遇到同类题,就能更快选出方向。
边界三连:边界三连:极端输入先过一遍。
几个高频追问,记住答法。
§3
参考代码
class Solution: def isBalanced(self, root): def height(node): if not node: return 0 left = height(node.left) if left == -1: return -1 # 左已不平衡,短路 right = height(node.right) if right == -1: return -1 if abs(left - right) > 1: return -1 # 当前不平衡 return max(left, right) + 1 return height(root) != -1看懂代码不等于写得出。盖住上面,自己默写一遍试试。卡在哪一行说不清,就点右下角问小欧。
§4
复杂度
- 时间复杂度:O(n),每个核心状态按算法要求处理固定次数
- 空间复杂度:O(h),只保存必要的辅助结构或递归栈
§5
可套用的代码模板
骨架:后序返回子树高度,子树不平衡或当前高度差>1 就返 -1 短路。
Python
# 平衡判断骨架 · 后序 + (-1)哨兵def height(node): if not node: return 0 L = height(node.left) if L == -1: return -1 # 左已不平衡,短路 R = height(node.right) if R == -1: return -1 if abs(L - R) > 1: return -1 # 当前不平衡 return max(L, R) + 1return height(root) != -1§6
易错点
✗ 错误写法:每个节点重复求高度
✓ 正确写法:后序一次返回高度并顺手判平衡
重复求会退化到 O(n²)
✗ 错误写法:自顶向下、每个点重新算高度
✓ 正确写法:自底向上后序,一次返回高度
自顶向下对每个节点都算一遍高度 → O(n²);后序自底向上 O(n)。
✗ 错误写法:height 和 isBalanced 分两次遍历
✓ 正确写法:合并:height 返回 -1 即表示不平衡
分开会重复遍历;用 -1 哨兵一次搞定。
§
面试追问把动画讲成自己的话
追问自顶向下为什么是 O(n²)?
对每个节点都从头算一次子树高度,高度计算 O(n),叠加 O(n²)。
追问自底向上怎么做到 O(n)?
递归一次返回高度顺便判断;用 -1 表示「这棵子树已不平衡」一路短路上传,每点只算一次。
追问高度和深度的区别?
高度从叶往上数、深度从根往下数;本题用高度(子树往上返回)。
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
下一题 · 树 5/23
→相同的树
LeetCode 100 · 简单 · 沿着 树 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
299道动画图解
37节语音讲解
28课数据结构
¥0.27折合 / 天
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
¥99 开通年卡 →
想成体系刷透这类套路?去图解算法专题