Algorithm

Binary Tree Left/Right Side View

Trees Pattern

Binary Tree Left/Right Side View

Stand to the right of the tree and look at it horizontally: at each depth you see exactly one node, the one furthest right on that level. Return those values ordered from the top of the tree downward. The left side view is the mirror question, taking the leftmost node of each level. The result has exactly one entry per level, and an empty tree returns an empty list.

CONSTRAINTS
  • The number of nodes in the tree is in the range [0, 100]
  • -100 <= Node.val <= 100
  • Exactly one value per level, ordered top to bottom
  • Visibility is by level position, not by which child slot a node occupies
EXAMPLE 1
Input: root = [1,2,3,null,5,null,4], right side view
Output: [1,3,4]
One value per depth: 1 at the top, then 3, then 4. The node 5 is hidden behind 4, which sits further right on the same level.
EXAMPLE 2
Input: root = [1,2,3,4], right side view
Output: [1,3,4]
At the bottom level only 4 exists, and it is a *left* child. It is visible because nothing else shares its level — being rightmost is about position on the level, not about being a right child.
EXAMPLE 3
Input: root = [1,2], right side view
Output: [1,2]
The root's right side is empty, so its left child is the only node on that level and therefore the visible one.
EXAMPLE 4
Input: root = [1,2,3,4,null,null,5], left side view
Output: [1,2,4]
Looking from the other side takes the first node of each level instead of the last. 5 is hidden behind 4.
If a node is a left child but nothing sits to its right on that level, is it visible?
Yes. Visibility depends on being last on the level, not on being someone's right child — the second example turns on exactly this.
Is there always exactly one value per level?
Yes, since every non-empty level has a rightmost node. The output length therefore equals the tree's height.
Does the left side view need different code?
Only in which node of each level you keep — the first instead of the last. Everything else is identical.
Can this be solved depth-first?
Yes: visit right before left and record the first node seen at each new depth. It gives the same answer in O(H) space instead of O(W), which is better on wide trees.

Look at the tree from one side and read off what you see. From the right you see the rightmost node of each level; from the left, the leftmost. Everything between is hidden. Either way the answer is one value per level — the two views are perfect mirrors of each other.

text
              1            left sees 1  |  right sees 1
             / \
            2   3          left sees 2  |  right sees 3
             \   \
              5   4        left sees 5  |  right sees 4

   left  side view:  [1, 2, 5]
   right side view:  [1, 3, 4]

First instinct — "just follow the right children down for the right view" (or left children for the left view) — is a trap. If that spine ends early but the other subtree runs deeper, those deeper levels are still visible; the edge node there just comes from the opposite side:

text
          1        right sees 1
         / \
        2   3      right sees 3
       /
      4            right sees 4   (a LEFT node — the right spine already ended!)
     /
    5              right sees 5

  right side view:  [1, 3, 4, 5]
  "just follow right children":  [1, 3]   <- wrongly stops, misses 4 and 5

Visibility is about position on a level, not which child slot a node sits in.

Right = last of each level, Left = first of each level

A level-by-level sweep hands both over. Sweep with a queue: freeze the level's size, pull exactly that many nodes; the queue gives them left to right, so within each level the first pulled is the leftmost (the left view) and the last pulled is the rightmost (the right view). Record the one you want, drop the rest.

python
if root is None: return []
out, queue = [], deque([root])
while queue:
    n = len(queue)                      # frozen level size
    for i in range(n):
        node = queue.popleft()
        want = (i == 0) if left_view else (i == n - 1)
        if want:                        # first node for left view, last for right
            out.append(node.val)
        if node.left:  queue.append(node.left)
        if node.right: queue.append(node.right)
return out

The two views are one line apart — i == 0 versus i == n - 1. Nothing about the walk changes, only which node you record.

Crucial Notestill enqueue left then right, even for the right view. Reversing the enqueue order to grab the first node instead happens to work, but the enqueue order also fixes the left-to-right meaning of every level below — flip it and you must flip your selection rule at every level too, and the two are easy to knock out of step. Leave the walk alone; change only the selection.
A cheaper-memory DFS version

There's a depth-first version that costs O(H) instead of O(W) — better on wide trees. For the right view, visit the right child first, carrying the depth; then the first node reached at any new depth is the rightmost there (at every fork above them, right descendants run before left). Record a node only when the answer list is still shorter than the depth reached — that's the "this depth is brand new" test. For the left view, mirror it: visit the left child first.

python
out = []
def walk(node, depth):
    if node is None: return
    if depth == len(out):        # first time we reach this depth
        out.append(node.val)     # so this is the edge node on this side
    walk(node.right, depth + 1)  # right FIRST for right view (swap for left view)
    walk(node.left,  depth + 1)
walk(root, 0)
Cost, and the takeaway

Both visit every node once: O(N) time. Memory differs — BFS costs O(W) (widest level), DFS costs O(H) (recursion depth). Wide bushy tree → DFS; deep chain → BFS. The habit: when a problem wants "the visible / first / extreme" node per level, the traversal is untouched — only the selection rule changes.

Interactive Strategy Visualization

Perspective Analysis

Simulate Left vs. Right visibility

1234567
Perspective Engine
Initialize DFS for right view...

Algorithm Rules

  • Depth Tracking: Use a Level variable to track vertical position.
  • Visibility Rule: First node visited at any depth is part of the view.
  • Priority Search: Prioritize Right child to see Right Side.
Memory Strategy
If level == result.size(), it's the first time we've reached this depth.
O(N) Time · O(W) Space Last Node Per Level (BFS)
O(N) Time · O(H) Space Right-First DFS With Depth