SWE · Coding

Meta 后序求树最大值:返回子问题、不用全局状态

在限定Postorder与禁止共享状态的条件下,让每个递归返回其子树最大值。

题目重点:在限定Postorder与禁止共享状态的条件下,让每个递归返回其子树最大值。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练普通二叉树数值可负,空子树None;禁止global/nonlocal/函数属性累计答案,但局部变量与函数返回值可用。若“function var”有更严格定义需要现场确认。
  • 输入是树,无共享子图或环;返回最大value不是最大路径和,也不是BST最大值专走右边。

解题路线

  1. 先递归left,再递归right,最后处理node.value,所以顺序为后序。左右调用只返回各自子树最大值,当前局部选择max(自身,存在的左答案,存在的右答案)。
  2. None表示不存在,不用0初始化。全负树[-3,-8,-5]结果−3,如果用0作默认会得到不在树里的数。
  3. 归纳:叶子返回自己最大;假设左右返回正确,整棵子树所有节点恰在自身/左/右三个集合,三者最大就是正确值,无需外部状态。
  4. 每次调用局部数据只含常数个候选,递归结果向父流动。不用函数static属性或闭包max变量绕过限制;共享状态也会让两次调用互相污染。
  5. 深树可改显式后序stack保存就绪标记与子答案,依然无全局状态;但Python递归版本受运行时深度限制,不能承诺百万链安全。

手动走一遍

根−8、左−3、右−5时左右先返回−3/−5,根最后比较得−3。随后调用另一树根−10应返回−10,不继承此前−3。空树None。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

class Node:
    def __init__(self,value,left=None,right=None):self.value=value;self.left=left;self.right=right


def maximum_postorder(root):
    """No global/nonlocal/function attributes; subtree answers flow by return."""
    if root is None:return None
    left=maximum_postorder(root.left)
    right=maximum_postorder(root.right)
    candidates=[root.value]
    if left is not None:candidates.append(left)
    if right is not None:candidates.append(right)
    return max(candidates)

复杂度

O(N)时间,每节点处理一次;递归O(h)调用栈,局部候选列表长度≤3不引入O(N)单层数组。最坏退化树h=N,有递归深度风险。

易错点与追问

容易失分的边界

  • global变量重置漏掉会污染下一次调用。
  • 只因node.value最大就提前返回,会漏掉未遍历子树。

继续深挖

  • 若需同时返回max和其Node身份,可用(value,node)并规定tie。
  • 如何将返回式扩展为总和、节点数、树高而不新增共享变量?
✓已复制微信号!