题目重点:返回所有根到叶的路径字符串,使用共享当前路径和迭代回溯避免每节点复制。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练Node.value可转字符串,路径分隔符→在代码为ASCII ->,叶子无左右孩子;按左到右叶顺序返回,空树[]。
- 不是返回各路径和,非叶中间节点不形成完整输出。
解题路线
- 栈存(node,exitFlag)。进入时把value加入path并安排退出,先压right再left保证左先遍历。退出时pop当前值,恢复父路径。
- 只有左右都None才join当前path输出;单边节点不是叶,不提前输出。共享path避免把长路径list复制给每个child。
- exit事件确保遍历兄弟前清掉前一子树节点,否则路径会串上无关支路。输出字符串在叶子时独立创建,后续path变更不会改结果。
- 可递归DFS append/pop实现同样逻辑;迭代版本免递归深度限制,但仍需栈保存沿途与待处理分支。独立oracle沿每叶parent回走到root验证。
手动走一遍
根1左2且2右5,根右3,输出1->2->5、1->3。若2只有右5,不能将1->2也输出;空树没有空路径。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def root_leaf_paths(root):
"""Left-to-right leaf order, '->' text, empty tree []; stringifiable values."""
if root is None:return []
result=[];path=[];stack=[(root,False)]
while stack:
node,exit=stack.pop()
if exit:path.pop();continue
path.append(str(node.value));stack.append((node,True))
if node.left is None and node.right is None:result.append('->'.join(path))
else:
if node.right is not None:stack.append((node.right,False))
if node.left is not None:stack.append((node.left,False))
return result
复杂度
遍历O(N),加输出总字符数S,时间O(N+S),辅助O(h)栈/当前path,输出O(S)。每叶都复制字符串是输出必需成本,不能把大量长路径说成整体O(N)。
易错点与追问
容易失分的边界
- 任一child缺失就当leaf,单边树截断。
- 保存同一个可变path引用到结果,后续pop会清空所有结果。
继续深挖
- 如果返回value数组而非字符串,输出空间按总路径节点数计算。
- 需要迭代器逐叶yield时,如何在yield后恢复path且不暴露可变引用?
