Before attempting this problem, you should be comfortable with:
The boundary of a binary tree consists of three parts traversed in order: the left boundary (top to bottom, excluding leaves), all leaf nodes (left to right), and the right boundary (bottom to top, excluding leaves). We handle each part separately: traverse down the left edge, collect all leaves via recursion, and traverse down the right edge while using a stack to reverse the order.
null, return an empty list.root.left and keep moving left (or right if left is null).root.right and keep moving right (or left if right is null).class Solution:
def isLeaf(self, t: Optional[TreeNode]) -> bool:
return t.left is None and t.right is None
def addLeaves(self, res: List[int], root: Optional[TreeNode]) -> None:
if self.isLeaf(root):
res.append(root.val)
else:
if root.left is not None:
self.addLeaves(res, root.left)
if root.right is not None:
self.addLeaves(res, root.right)
def boundaryOfBinaryTree(self, root: Optional[TreeNode]) -> List[int]:
res = []
if root is None:
return res
if not self.isLeaf(root):
res.append(root.val)
t = root.left
while t is not None:
if not self.isLeaf(t):
res.append(t.val)
if t.left is not None:
t = t.left
else:
t = t.right
self.addLeaves(res, root)
stack = []
t = root.right
while t is not None:
if not self.isLeaf(t):
stack.append(t.val)
if t.right is not None:
t = t.right
else:
t = t.left
while stack:
res.append(stack.pop())
return resWhere is the number of nodes in the tree
We can collect all boundary nodes in a single preorder traversal by tracking where each node belongs. Using a flag system, we mark nodes as: root (0), left boundary (1), right boundary (2), or internal (3). During traversal, we determine each child's flag based on the parent's flag and whether siblings exist. Left boundary nodes go directly to the result, right boundary nodes are collected in reverse order, and leaves are gathered separately.
left_boundary, right_boundary, and leaves.2), prepend its value to right_boundary.0 or 1), append its value to left_boundary.leaves.left_boundary + leaves + right_boundary and return.class Solution:
def boundaryOfBinaryTree(self, root: Optional[TreeNode]) -> List[int]:
left_boundary, right_boundary, leaves = [], [], []
self.preorder(root, left_boundary, right_boundary, leaves, 0)
left_boundary.extend(leaves)
left_boundary.extend(right_boundary)
return left_boundary
def is_leaf(self, cur):
return cur.left is None and cur.right is None
def is_right_boundary(self, flag):
return flag == 2
def is_left_boundary(self, flag):
return flag == 1
def is_root(self, flag):
return flag == 0
def left_child_flag(self, cur, flag):
if self.is_left_boundary(flag) or self.is_root(flag):
return 1
elif self.is_right_boundary(flag) and cur.right is None:
return 2
else:
return 3
def right_child_flag(self, cur, flag):
if self.is_right_boundary(flag) or self.is_root(flag):
return 2
elif self.is_left_boundary(flag) and cur.left is None:
return 1
else:
return 3
def preorder(self, cur, left_boundary, right_boundary, leaves, flag):
if cur is None:
return
if self.is_right_boundary(flag):
right_boundary.insert(0, cur.val)
elif self.is_left_boundary(flag) or self.is_root(flag):
left_boundary.append(cur.val)
elif self.is_leaf(cur):
leaves.append(cur.val)
self.preorder(cur.left, left_boundary, right_boundary, leaves, self.left_child_flag(cur, flag))
self.preorder(cur.right, left_boundary, right_boundary, leaves, self.right_child_flag(cur, flag))Where is the number of nodes in the tree
Leaf nodes should only appear once in the leaves section, not in the left or right boundary. Adding a leaf while traversing the left boundary causes duplicates in the result.
# Wrong: not checking for leaf before adding to boundary
while t is not None:
res.append(t.val) # Should check: if not isLeaf(t)
t = t.left if t.left else t.rightThe right boundary must be added in bottom-to-top order. A common mistake is adding nodes directly to the result during traversal (top-to-bottom), instead of using a stack or reversing at the end.
When traversing the left boundary, if a node has no left child, you must continue with the right child (and vice versa for the right boundary). Stopping traversal at missing children misses boundary nodes deeper in the tree.