二叉树
一句话:几乎所有二叉树题都能套进同一个框架——“整棵树的答案 = 用根节点的信息,组合左右子树各自的答案”。想清楚”子树需要返回什么信息给父节点”,代码基本就写出来了;唯一的例外是层序遍历,它天生是迭代(BFS)而非递归的活。
递归框架:子树返回什么
104-二叉树的最大深度、543-二叉树的直径、124-二叉树中的最大路径和 表面难度差很大,套路完全一样:写一个递归函数,让它返回”以当前节点为根、只往下延伸时的最优值”,同时在函数内部用左右子树的返回值去更新一个”跨过当前节点”的全局答案。
543里子树返回”从该节点往下的最长链长度”,全局答案更新为”左链长度 + 右链长度”(跨过当前节点的路径)。124是同一个模板换成”最大路径和”:子树返回时要和 0 取 max(负贡献不如不要),全局答案同样是”左 + 右 + 当前节点值”跨节点组合。
关键教训:子树”返回给父节点用于继续递归”的值,和”更新全局答案”的值,往往不是同一个东西——返回值必须是”能继续延伸的单侧最优”,全局答案才是”两侧拼接的整体最优”,把这两者混为一谈是这类题最常见的错误。
98-验证二叉搜索树、230-BST中第K小的元素 利用的是 BST 的中序遍历天然有序这一性质,本质也是”递归时带着信息(上下界,或者计数)往下传”的变体,属于同一个框架的不同参数。
105-从前序与中序遍历构造二叉树 反过来利用递归框架构造树:前序的第一个元素是根,在中序里定位它即可切出左右子树的范围,递归重建——这也是”用递归划分左右子树”的思想,只是方向从”消费树”变成”生产树”。
BFS:唯一的迭代主场
102-层序遍历、199-二叉树的右视图 必须用队列做 BFS,而不是递归——因为这两题都需要按层处理(每层做统计,或每层只取最后一个),递归天然按”深度优先”的顺序访问节点,拿不到”同一层”这个分组,所以只能老老实实用队列,每轮把当前队列的全部节点出队、把它们的子节点入队。
序列化:树的线性表示
297-二叉树的序列化与反序列化 本质是”给递归框架配一个可逆的线性编码”:前序遍历序列化时把空节点也显式记录(用占位符),反序列化时按同样的顺序消费序列重建——空节点不省略是能够无歧义还原结构的关键,否则同一个前序序列可能对应多棵树。
919-完全二叉树插入器 利用的是完全二叉树”按层序编号后,子节点下标可以直接计算”的性质(下标 i 的子节点是 2i+1/2i+2),插入时用层序遍历(队列)找到第一个还有空位的节点,是 BFS 而非递归框架的应用。