SWE · Coding

Amazon 树的序列化:空指针标记与严格解码

用前序token保存树形,迭代解码避免深链递归溢出并拒绝残缺输入。

题目重点:用前序token保存树形,迭代解码避免深链递归溢出并拒绝残缺输入。

题意与假设

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

  • 题型被描述为接近二叉树序列化/反序列化,实际复杂结构未披露。练习定义整数节点、None空孩子、前序token列表;不说实际面试就是该格式。
  • 输入是真树无环/共享节点,整数0合法,bool不作为整数节点;空树编码[None]而非空列表。传输层JSON/二进制格式需另定义。

解题路线

  1. 序列化用stack先放root,弹节点输出值并压right再left,空节点输出None。空标记使左右缺失位置保留;只输出前序值不能唯一重建一般树。
  2. 解码stack保存待填(node,left/right)槽,消费一个token填一个槽;非空孩子带来两个新槽,空标记不带来新槽。先完成left子树再填right,顺序与前序一致。
  3. 输入结束仍有槽是缺子树,槽已空又有token是多余数据。拒绝这些情况而非返回貌似成功的截断树;schema的值类型检查不能靠truthiness。
  4. 独立检验可用槽总数从1开始,每个None减1、非空净加1,严格结束于0且中间未过早用完;再用路径→value映射检查重建形状,不仅比较两次输出。
  5. 如果输入实际是图,重复节点要ID及引用标签;本树格式会丢身份/遇环无限展开。实际题的特殊结构留待澄清,不能用熟题token格式强行覆盖。

手动走一遍

树1仅左孩子2编码[1,2,None,None,None];树1仅右孩子2为[1,None,2,None,None],空标记区分它们。[1,None]残缺,[None,2]多余,均拒绝。

Python 参考实现

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

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

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

def _value(value):
    if not isinstance(value,int) or isinstance(value,bool):raise ValueError('integer node')
    return value

def serialize(root):
    tokens=[];stack=[root]
    while stack:
        node=stack.pop()
        if node is None:tokens.append(None)
        else:
            tokens.append(_value(node.value));stack.append(node.right);stack.append(node.left)
    return tokens

def deserialize(tokens):
    stream=iter(tokens);missing=object();first=next(stream,missing)
    if first is missing:raise ValueError('empty stream')
    root=None if first is None else Node(_value(first))
    stack=[] if root is None else [(root,0)]
    for value in stream:
        if not stack:raise ValueError('extra tokens')
        node,slot=stack.pop()
        child=None if value is None else Node(_value(value))
        if slot==0:node.left=child;stack.append((node,1))
        else:node.right=child
        if child is not None:stack.append((child,0))
    if stack:raise ValueError('missing child tokens')
    return root

复杂度

N节点序列长度2N+1,时间O(N)。序列化stack与解码槽stackO(H),最坏深链O(N);返回树/完整tokens各O(N)。传输字符串含数值位宽后大小不只是token数。

易错点与追问

容易失分的边界

  • 空孩子不输出,丢树形。
  • value0当空节点。
  • 默默忽略多余token或接受残缺输入。

继续深挖

  • 如果要可流式解码,怎样用迭代器及长度/资源预算?
  • 图共享子树的身份格式如何与树格式区分?
✓已复制微信号!