Boundary Traversal of Binary Tree in DSA C++ - Time & Space Complexity
We want to understand how the time taken grows when we do a boundary traversal of a binary tree.
Specifically, how the number of nodes affects the work done to collect the boundary nodes.
Analyze the time complexity of the following code snippet.
void printBoundary(Node* root) {
if (!root) return;
cout << root->data << " ";
printLeftBoundary(root->left);
printLeaves(root->left);
printLeaves(root->right);
printRightBoundary(root->right);
}
// Helper functions traverse parts of the tree
void printLeftBoundary(Node* node) {
while (node) {
if (!isLeaf(node)) cout << node->data << " ";
if (node->left) node = node->left;
else node = node->right;
}
}
This code prints the boundary nodes of a binary tree in anti-clockwise order: root, left boundary, leaves, and right boundary.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Traversing nodes in the tree 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 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 work grows roughly in direct proportion to the number of nodes.
Time Complexity: O(n)
This means the time taken 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, including leaves and internal nodes, so it ends up visiting all nodes once.
Understanding this traversal helps you reason about tree traversals and how to efficiently visit nodes in a specific order, a useful skill in many coding problems.
"What if we changed the tree to be skewed (all nodes only have one child)? How would the time complexity change?"
Practice
Solution
Step 1: Understand boundary traversal components
Boundary traversal includes the left boundary (excluding leaves), all leaf nodes, and the right boundary (excluding leaves) in reverse order.Step 2: Combine all parts in order
Traverse left boundary top-down, then leaves left to right, then right boundary bottom-up to get the full boundary traversal.Final Answer:
Left boundary, leaves, and right boundary nodes in order -> Option AQuick Check:
Boundary traversal = Left boundary + Leaves + Right boundary [OK]
- Including leaf nodes twice in left or right boundary
- Ignoring right boundary order (should be bottom-up)
- Confusing boundary traversal with level order
Solution
Step 1: Identify correct parameter type for tree node
Binary tree nodes are passed as pointers (Node*), not by value (Node), to avoid copying the entire subtree.Step 2: Check return type for printing function
Printing functions usually return void as they output directly and do not return a value.Final Answer:
void printLeftBoundary(Node* root); -> Option AQuick Check:
Pointer parameter + void return = correct signature [OK]
- Passing node by value causing unnecessary copies
- Using int return type for printing functions
- Missing pointer symbol (*) in parameter
1
/ \
2 3
/ \ \
4 5 6
/ \ /
7 8 9
Solution
Step 1: Identify left boundary nodes excluding leaves
Left boundary: 1, 2 (4 is leaf, so excluded here)Step 2: Collect all leaf nodes left to right
Leaves: 4, 7, 8, 9Step 3: Identify right boundary nodes excluding leaves in bottom-up order
Right boundary: 6, 3Step 4: Combine all parts
Boundary traversal = [1, 2] + [4, 7, 8, 9] + [6, 3] = [1, 2, 4, 7, 8, 9, 6, 3]Final Answer:
[1, 2, 4, 7, 8, 9, 6, 3] -> Option BQuick Check:
Left boundary + leaves + right boundary = [1, 2, 4, 7, 8, 9, 6, 3] [OK]
- Including leaf nodes twice in boundary
- Wrong order of right boundary nodes
- Missing some leaf nodes
void printRightBoundary(Node* root) {
if (!root) return;
if (root->right) {
printRightBoundary(root->right);
} else if (root->left) {
printRightBoundary(root->left);
}
std::cout << root->data << " ";
}Solution
Step 1: Analyze printing condition in recursion
The function prints every node after recursive calls, including leaf nodes which should be excluded from right boundary printing.Step 2: Identify missing leaf node check
There is no check to skip printing leaf nodes, so leaf nodes get printed incorrectly as part of right boundary.Final Answer:
It prints leaf nodes which should be excluded -> Option CQuick Check:
Leaf nodes must be excluded from right boundary [OK]
- Printing leaf nodes in boundary traversal
- Not checking for null nodes before recursion
- Confusing order of printing nodes
Solution
Step 1: Understand edge cases in boundary traversal
Single node tree or skewed trees may cause duplicates if leaves are included in boundaries without checks.Step 2: Use approach that prints root, left boundary excluding leaves, leaves, right boundary excluding leaves, and skip duplicates
This ensures no node is printed twice and all edge cases are handled correctly.Final Answer:
Print root, then left boundary excluding leaves, then leaves, then right boundary excluding leaves, skipping duplicates -> Option DQuick Check:
Exclude leaves in boundaries + skip duplicates [OK]
- Printing leaves twice in skewed trees
- Ignoring root node in traversal
- Using level order which is not boundary traversal
Ready to prove it?
Pass the test and this pattern moves unknown
