题目重点:把二叉树节点映射到水平列,按深度决定底部可见节点,并明确同深同列的训练并列规则。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 根列为 0,左子节点列减 1,右子节点列加 1;深度从根 0 开始。输出按列从小到大。
- 同列同深时,训练代码取 BFS 左到右遍历中较晚访问的节点;其他平台可能有不同 tie-break,应先询问。
解题路线
- BFS 队列携带 (node,column,depth),每取一节点,用该列现有记录与当前深度比较,较深者覆盖。
- 同深时按训练并列规则让后访问者覆盖。BFS 先左后右入队,队列在同一深度保持从左到右的顺序。
- 遍历结束后按 column 排序并输出保留的值;如果列跨度受 N 限制,也可维护 min/max column 顺次读出。
- 每列保留的深度不小于该列已访问所有节点,因此扫描完成时就是底部节点;同深规则保证结果确定。
手动走一遍
根 1,左子 2、右子 3;2 的右子 4 与 3 的左子 5 都在列 0、深度 2。按训练规则 BFS 后到的 5 覆盖 4,列 -1/0/1 的结果为 [2,5,3]。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
"""Bottom view with later BFS order winning equal-depth ties."""
from collections import deque
class TreeNode:
def __init__(self, value: int, left: "TreeNode | None" = None, right: "TreeNode | None" = None):
self.value = value
self.left = left
self.right = right
def bottom_view(root: TreeNode | None) -> list[int]:
if root is None:
return []
queue = deque([(root, 0, 0)])
seen: dict[int, tuple[int, int]] = {}
while queue:
node, column, depth = queue.popleft()
previous = seen.get(column)
if previous is None or depth >= previous[0]:
seen[column] = (depth, node.value)
if node.left is not None:
queue.append((node.left, column - 1, depth + 1))
if node.right is not None:
queue.append((node.right, column + 1, depth + 1))
return [seen[column][1] for column in sorted(seen)]
复杂度
N 个节点遍历 O(N),对至多 N 个列排序 O(C log C),空间 O(W+C),W 为 BFS 最大层宽。若用有序映射,时间可 O(N log C)。
易错点与追问
容易失分的边界
- 只保留每列最后访问节点,却未说明遍历顺序或深度;DFS 的最后访问不一定是最深。
- 把 top view 的最浅节点规则误用于 bottom view。
- 同深同列不问并列规则,导致与测试平台期望不一致。
继续深挖
- 若要求同深时优先更左的节点,比较条件如何改?
- vertical order traversal 与 bottom view 的输出语义有何不同?
