Bottom View of Binary Tree in DSA Python - Time & Space Complexity
We want to understand how the time needed to find the bottom view of a binary tree changes as the tree grows.
How does the work increase when the tree has more nodes?
Analyze the time complexity of the following code snippet.
from collections import deque
def bottom_view(root):
if not root:
return []
queue = deque([(root, 0)])
hd_node_map = {}
while queue:
node, hd = queue.popleft()
hd_node_map[hd] = node.val
if node.left:
queue.append((node.left, hd - 1))
if node.right:
queue.append((node.right, hd + 1))
return [hd_node_map[hd] for hd in sorted(hd_node_map)]
This code finds the bottom view of a binary tree by traversing nodes level by level and tracking their horizontal distances.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that visits each node once.
- How many times: Exactly once per node in the tree (n times).
As the number of nodes grows, the code visits each node once, so the work grows directly with the number of nodes.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 visits |
| 100 | About 100 visits |
| 1000 | About 1000 visits |
Pattern observation: The operations increase linearly as the tree size increases.
Time Complexity: O(n)
This means the time to find the bottom view grows directly with the number of nodes in the tree.
[X] Wrong: "The time complexity is more than linear because we sort the horizontal distances at the end."
[OK] Correct: Sorting happens on the horizontal distances, which are at most the width of the tree, usually much smaller than n, so it does not change the overall linear time complexity.
Understanding how to analyze tree traversals like this helps you explain your approach clearly and shows you can reason about efficiency in real problems.
"What if we used a recursive approach instead of a queue? How would the time complexity change?"
Practice
bottom view of a binary tree represent?Solution
Step 1: Understand the bottom view concept
The bottom view shows nodes visible when looking at the tree from below, meaning the lowest nodes at each horizontal distance.Step 2: Compare with other views
Top view shows nodes from above, left and right views show nodes from sides, so bottom view is unique for bottom perspective.Final Answer:
Nodes visible when the tree is viewed from the bottom -> Option DQuick Check:
Bottom view = visible nodes from below [OK]
- Confusing bottom view with top view
- Thinking bottom view shows all leaf nodes
- Mixing bottom view with side views
Solution
Step 1: Identify the need for horizontal distance mapping
We need to map horizontal distances to nodes to know which node is visible at each position.Step 2: Choose the data structure
A hash map (dictionary) stores horizontal distance as key and node value as value, updating with the bottom-most node.Final Answer:
Hash Map (Dictionary) -> Option AQuick Check:
Use dictionary to map horizontal distance to node [OK]
- Using stack which is LIFO and not suitable here
- Using queue alone without mapping distances
- Using linked list which is inefficient for key-value mapping
20
/ \
8 22
/ \ \
5 3 25
/ \
10 14
Solution
Step 1: Assign horizontal distances and find bottom nodes
Horizontal distances: 20(0), 8(-1), 22(1), 5(-2), 3(0), 25(2), 10(-1), 14(1). Bottom nodes at each distance: -2:5, -1:10, 0:3, 1:14, 2:25.Step 2: List bottom view nodes in order of horizontal distance
From left to right: 5, 10, 3, 14, 25.Final Answer:
[5, 10, 3, 14, 25] -> Option AQuick Check:
Bottom view nodes by horizontal distance = [5,10,3,14,25] [OK]
- Not updating bottom node when a lower node appears
- Mixing horizontal distances order
- Including nodes not visible from bottom
def bottom_view(root):
if not root:
return []
queue = [(root, 0)]
hd_node = {}
while queue:
node, hd = queue.pop()
hd_node[hd] = node.val
if node.left:
queue.append((node.left, hd - 1))
if node.right:
queue.append((node.right, hd + 1))
return [hd_node[hd] for hd in sorted(hd_node)]
What is the main error in this code?Solution
Step 1: Analyze queue usage and traversal order
The code uses queue.pop() which removes last element (LIFO), making it behave like a stack, causing depth-first traversal instead of breadth-first.Step 2: Understand impact on bottom view calculation
Breadth-first traversal is needed to process nodes level by level to correctly update bottom nodes. Using pop() breaks this order.Final Answer:
Using pop() removes last element, causing wrong traversal order -> Option BQuick Check:
Use pop(0) or deque.popleft() for BFS [OK]
- Using pop() instead of pop(0) for queue
- Ignoring empty root check
- Incorrect horizontal distance updates
Solution
Step 1: Understand the need to track depth
To show the bottom-most node at each horizontal distance, we must know which node is deepest (greatest depth).Step 2: Modify dictionary to store value and depth
Store a tuple (node value, depth) for each horizontal distance. Update only if new node's depth is greater than stored depth.Final Answer:
Store both node value and depth in the dictionary, update only if new node depth is greater -> Option CQuick Check:
Track depth to update bottom view nodes correctly [OK]
- Ignoring depth and overwriting nodes incorrectly
- Storing all nodes without filtering by depth
- Picking first or last node without depth check
Ready to prove it?
Pass the test and this pattern moves unknown
