Boundary Traversal of Binary Tree in DSA Python - Time & Space Complexity
We want to understand how the time needed to do a boundary traversal changes as the tree grows.
Specifically, how many steps does it take to visit the boundary nodes of a binary tree?
Analyze the time complexity of the following code snippet.
class Node:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def printBoundary(root):
if not root:
return
print(root.val) # print root
printLeftBoundary(root.left)
printLeaves(root.left)
printLeaves(root.right)
printRightBoundary(root.right)
# Assume printLeftBoundary, printLeaves, printRightBoundary are helper functions
This code prints the boundary nodes of a binary tree in order: root, left edge, leaves, and right edge.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive traversal of nodes to print left boundary, leaves, and right boundary.
- How many times: Each node is visited at most once during these traversals.
As the number of nodes (n) increases, the traversal visits each node once to check if it belongs to the boundary.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 visits |
| 100 | About 100 visits |
| 1000 | About 1000 visits |
Pattern observation: The number of operations grows roughly in direct proportion to the number of nodes.
Time Complexity: O(n)
This means the time to do the boundary traversal grows linearly with the number of nodes in the tree.
[X] Wrong: "The boundary traversal only visits boundary nodes, so it must be faster than visiting all nodes."
[OK] Correct: To find boundary nodes, the algorithm must check many nodes to decide if they are leaves or edges, so it ends up visiting all nodes anyway.
Understanding this traversal's time complexity helps you explain how tree traversals scale and shows your grasp of recursive tree processing.
"What if the tree is skewed (like a linked list)? How would the time complexity change?"
Practice
Solution
Step 1: Understand boundary traversal components
Boundary traversal includes nodes on the left edge, all leaf nodes, and nodes on the right edge of the tree.Step 2: Compare options with definition
Only Left boundary, leaves, and right boundary nodes correctly lists left boundary, leaves, and right boundary nodes.Final Answer:
Left boundary, leaves, and right boundary nodes -> Option AQuick Check:
Boundary traversal = left boundary + leaves + right boundary [OK]
- Confusing boundary traversal with level order traversal
- Ignoring leaf nodes in boundary traversal
- Including all nodes instead of just edges and leaves
Solution
Step 1: Identify typical function signature
Boundary traversal usually takes the root node as input and returns the traversal list.Step 2: Check options for correct signature
def boundaryTraversal(root): takes only root as input, which is standard and sufficient.Final Answer:
def boundaryTraversal(root): -> Option DQuick Check:
Function signature with root only is correct [OK]
- Adding unnecessary parameters like left and right
- Missing root parameter
- Using empty parameter list
1 / \ 2 3 / \ \ 4 5 6 / \ / 7 8 9
Solution
Step 1: Identify left boundary nodes
Left boundary nodes are 1, 2, 4 (excluding leaf duplicates).Step 2: Identify leaf nodes
Leaves are 4, 7, 8, 9, 6.Step 3: Identify right boundary nodes
Right boundary nodes are 3, 6 (excluding leaf duplicates), so only 3.Step 4: Combine nodes in order
Boundary traversal = left boundary (1,2,4) + leaves (7,8,9,6) + right boundary reversed (3) = [1, 2, 4, 7, 8, 9, 6, 3]Final Answer:
[1, 2, 4, 7, 8, 9, 6, 3] -> Option AQuick Check:
Boundary traversal output matches [1, 2, 4, 7, 8, 9, 6, 3] [OK]
- Including leaf nodes twice in boundary
- Missing right boundary node 3
- Incorrect order of nodes
def boundaryTraversal(root):
result = []
def leftBoundary(node):
if node and (node.left or node.right):
result.append(node.val)
if node.left:
leftBoundary(node.left)
else:
leftBoundary(node.right)
def leaves(node):
if node:
leaves(node.left)
if not node.left and not node.right:
result.append(node.val)
leaves(node.right)
def rightBoundary(node):
if node and (node.left or node.right):
if node.right:
rightBoundary(node.right)
else:
rightBoundary(node.left)
result.append(node.val)
if root:
result.append(root.val)
leftBoundary(root.left)
leaves(root.left)
leaves(root.right)
rightBoundary(root.right)
return result
Solution
Step 1: Analyze leftBoundary function
Left boundary adds nodes with children but does not exclude leaf nodes explicitly, so leaf nodes can be added twice.Step 2: Check leaves and rightBoundary functions
Leaves function correctly adds leaf nodes; rightBoundary appends after recursion, which is correct.Step 3: Identify bug
Left boundary includes leaf nodes causing duplicates in result.Final Answer:
Left boundary includes leaf nodes causing duplicates -> Option CQuick Check:
Left boundary must exclude leaves to avoid duplicates [OK]
- Appending right boundary nodes before recursion
- Not adding root node
- Leaves function missing some leaves
Solution
Step 1: Understand boundary traversal with single-child nodes
When a node has only one child, boundary traversal must follow that child to include all boundary nodes.Step 2: Apply traversal rules
For left boundary, choose left child if exists; if not, choose right child. For right boundary, choose right child if exists; if not, choose left child.Step 3: Avoid duplicates by excluding leaves in boundary functions
Leaves are handled separately to avoid duplicates.Final Answer:
Traverse left boundary by always choosing left child if present, else right child; similarly for right boundary, choose right child if present, else left child -> Option BQuick Check:
Follow child presence rules to cover all boundary nodes [OK]
- Skipping single-child nodes causing missing boundary nodes
- Including all nodes causing duplicates
- Ignoring leaf nodes in traversal
Ready to prove it?
Pass the test and this pattern moves unknown
