Binary Tree Right Side View

Medium BFS

Problem

Given the root of a binary tree, return the values of the nodes visible from the right side, ordered from top to bottom.

  • The number of nodes in the tree is in the range [0, 100]
  • −100 ≤ Node.val ≤ 100

Example

Input: root = [1,2,3,null,5,null,4]
Output: [1,3,4]

The tree structure is: 1 / \ 2 3 \ \ 5 4 A brute-force approach would be to traverse the tree and record all nodes at each level, then pick the rightmost node. The algorithm uses a breadth-first search (BFS) to traverse level by level. At each level, it processes all nodes, updating the rightmost node seen. For the example, at level 0, node 1 is the only node and thus the rightmost. At level 1, nodes 2 and 3 are processed; 3 is the rightmost. At level 2, nodes 5 and 4 are processed; 4 is the rightmost. Collecting these rightmost nodes yields [1,3,4].

Approach

Straightforward Solution

A naive approach would be to perform a DFS and track the rightmost node at each depth, but this requires careful state management and can be less intuitive.

Core Observation

The right side view of a binary tree corresponds to the rightmost node at each depth level when traversed level by level.

Path to Optimal

Recognizing that BFS naturally processes nodes level by level, the algorithm uses a queue to traverse the tree breadth-first. At each level, the last node processed is the rightmost node visible from that level. By recording this node's value, the algorithm efficiently constructs the right side view.

Optimal Approach

Use a queue initialized with the root node. For each level, iterate over all nodes currently in the queue, updating a variable to track the last node processed. Enqueue the children of each node for the next level. After processing the level, append the last node's value to the result list. Continue until the queue is empty. This guarantees an O(n) time complexity and O(n) space complexity.

Time

O(n)

Each node is enqueued and dequeued exactly once during the BFS traversal, resulting in linear time proportional to the number of nodes.

Space

O(n)

The queue can hold up to the maximum number of nodes at any level, which in the worst case is proportional to n/2 (for a balanced tree), resulting in O(n) auxiliary space.

Pattern Spotlight

BFS (Level-Order Traversal for Layered State Exploration)

When a problem requires information about nodes at each depth or layer, use BFS to process nodes level by level, enabling direct access to the first or last node at each level without complex state tracking.

Solution

1import collections
2
3class Solution:
4 def rightSideView(self, root: TreeNode) -> list[int]:
5 res = []
6 if not root:
7 return res
8
9 q = collections.deque([root])
10
11 while q:
12 right_side = None
13 q_len = len(q)
14
15 for i in range(q_len):
16 node = q.popleft()
17 if node:
18 right_side = node
19 q.append(node.left)
20 q.append(node.right)
21
22 if right_side:
23 res.append(right_side.val)
24
25 return res

Step-by-Step Solution

1

Initialize Result List Before BFS Traversal

5res = []

Objective

To create the output list that will store the visible rightmost node value from each level.

Key Insight

The BFS loop determines one visible node per level, but those values need a stable container from the start. Initializing the result list before any queue logic makes the output flow explicit and also supports the empty-tree case cleanly.

Interview Quick-Check

Core Logic

Create the result list before traversal so each completed level can append one visible value.

State & Boundaries

The result container must exist even when the tree is empty, because the empty-tree case returns it directly.

2

Return Empty List for Empty Tree

6if not root:
7 return res

Objective

To handle the edge case where the input tree is empty by returning an empty result immediately.

Key Insight

Checking for an empty root upfront prevents unnecessary processing and avoids errors from operating on a null tree. This early exit is a standard defensive programming practice that simplifies the main logic by guaranteeing the root exists thereafter.

Interview Quick-Check

State & Boundaries

Return immediately if root is None, as no nodes are visible from the right side.

3

Traverse Tree Level-by-Level Using a Queue

9q = collections.deque([root])
11while q:
12 right_side = None
13 q_len = len(q)
15 for i in range(q_len):
16 node = q.popleft()
17 if node:
18 right_side = node
19 q.append(node.left)
20 q.append(node.right)
22 if right_side:
23 res.append(right_side.val)

Objective

To perform a breadth-first search that processes nodes level by level, tracking the rightmost node at each level.

Key Insight

BFS naturally groups nodes by depth, allowing the algorithm to identify the rightmost node by updating a variable during the iteration over each level's nodes. Enqueuing children ensures the next level is ready for processing. This approach avoids complex recursion or additional data structures to track node positions.

Interview Quick-Check

Core Logic

Use a queue to process nodes level by level, updating the rightmost node variable as nodes are dequeued.

State & Boundaries

At each level, process exactly the number of nodes currently in the queue to isolate levels.

Common Pitfalls & Bugs

Appending None children to the queue can cause unnecessary processing; checking node existence before enqueueing children avoids this.

Complexity

Each node is enqueued and dequeued once, ensuring O(n) time and space complexity.

4

Return the Collected Right Side View

25return res

Objective

To return the list of rightmost node values collected from each level after BFS completes.

Key Insight

After processing all levels, the result list contains exactly one node per level: the rightmost visible node. Returning this list completes the solution.

Interview Quick-Check

Core Logic

Returning the accumulated list of rightmost nodes provides the final right side view.

Line Analysis

This solution has 1 Critical line interviewers watch for.

Line 18 Critical
right_side = node

Update the rightmost node to the current node.

This assignment is critical because it captures the rightmost node at the current level; updating it for every valid node ensures the last one processed is the visible node from the right side.

Line 9 Core
q = collections.deque([root])

Initialize a queue with the root node for BFS traversal.

The queue is the fundamental data structure enabling level-order traversal, starting with the root as the first node to process.

Line 16 Core
node = q.popleft()

Remove the next node from the queue for processing.

Dequeuing nodes in FIFO order ensures BFS processes nodes level by level from left to right.

Line 22 Core
if right_side:

If a rightmost node was found at this level, append its value to the result list.

Appending the rightmost node's value after processing the entire level ensures the result captures the visible node from the right side at that depth.

Line 25 Core
return res

Return the list of rightmost node values after BFS completes.

Returning the accumulated list provides the final answer representing the right side view of the binary tree.

Line 6 Core
if not root:

Check if the root is None (empty tree).

This early check prevents unnecessary processing and ensures the algorithm handles the edge case of an empty tree gracefully.

Line 7 Core
return res

Return an empty list if the tree is empty.

Returning immediately avoids errors and correctly represents that no nodes are visible from the right side in an empty tree.

Line 12 Core
right_side = None

Initialize a variable to track the rightmost node at the current level.

Resetting this variable at each level allows capturing the last node processed, which corresponds to the rightmost node visible from that level.

Line 13 Core
q_len = len(q)

Record the number of nodes at the current level.

Knowing the level size allows processing exactly one level's nodes per iteration, isolating levels in the BFS traversal.

Line 17 Core
if node:

Check if the dequeued node is not None.

This check prevents processing null nodes, avoiding errors and unnecessary queue insertions.

Line 19 Core
q.append(node.left)

Add the left child of the current node to the queue.

Enqueuing the left child prepares the next level for BFS traversal, ensuring all nodes are eventually processed.

Line 20 Core
q.append(node.right)

Add the right child of the current node to the queue.

Enqueuing the right child alongside the left child maintains the correct BFS order and completeness of traversal.

Line 23 Core
res.append(right_side.val)

Add the rightmost node's value to the output list.

This line finalizes the capture of the right side view for the current level, building the final output incrementally.

Line 11 Standard
while q:

Continue processing while there are nodes in the queue.

The loop ensures all levels are processed until no nodes remain, enabling complete traversal of the tree.

Line 15 Standard
for i in range(q_len):

Iterate over all nodes at the current level.

This loop processes each node in the current level, enabling the algorithm to identify the rightmost node and enqueue children for the next level.

Line 5 Standard
res = []

Initialize the output list that will store the right-side view.

The result list accumulates exactly one visible node value per level, so it must exist before any empty-tree return or BFS processing begins.

Test Your Understanding

Why does the BFS approach guarantee that the last node processed at each level is the rightmost visible node?

Because BFS processes nodes in order from left to right at each level, the last node dequeued at that level is the rightmost node, which is exactly the node visible from the right side.

Related Problems

BFS pattern

Don't just read it. Drill it.

Reconstruct Binary Tree Right Side View from memory until it sticks. AlgoDrill blanks out key lines and makes you fill them back in, step by step.

Unlock the Binary Tree Right Side View drill

or drill a free problem