Right View of a Binary Tree

Problem and examples

Given a binary tree, return the right view of the tree using an iterative level-order traversal approach. The right view of a binary tree includes the last node at each level when the tree is viewed from the right side.
Input Tree Right View Output Description
[1, 2, 3, 4, 5, null, 6] [1, 3, 6] Standard case: Nodes visible from the right at each level
[1] [1] Single-node tree: root is the only visible node
[] [] Empty tree: no nodes to view from any side
[1, 2, null, 3, null, null, null, 4] [1, 2, 3, 4] Left-skewed tree: right view includes one node per level
[1, null, 2, null, null, null, 3] [1, 2, 3] Right-skewed tree: all nodes are visible in the right view
[10, 20, 30, null, 25, null, 35] [10, 30, 35] Balanced tree with both left and right children

Explore Right View of a Binary Tree - Iterative

Load an example or enter your own input. Use the player controls to follow each change.

Understanding the Problem

The Right View of a Binary Tree refers to the set of nodes visible when the tree is viewed from the right side. At each level of the tree, we only see the rightmost node. Our task is to return a list of such nodes, ordered from top to bottom.

To solve this, we need to understand how trees are structured and how to explore them level by level. We will use a level-order traversal approach (like BFS), and for each level, we will record the last node encountered—this node represents what we see from the right side at that level.

Step-by-Step Solution with Example

Step 1: Understand the input format

The binary tree is typically represented as a level-order list like [1, 2, 3, null, 5, null, 4]. Each element corresponds to a node in the tree, and null indicates a missing child.

Step 2: Perform level-order traversal

We use a queue to explore the tree level by level. For each level, we loop through all nodes, and we keep track of the last node encountered in that level—this is the one visible from the right side.

Step 3: Apply the logic on the example

Let’s consider the tree represented by [1, 2, 3, null, 5, null, 4]. This corresponds to:

    1
   /   2   3
           5    4

Now we traverse level by level:

  • Level 1: Nodes = [1] → Rightmost = 1
  • Level 2: Nodes = [2, 3] → Rightmost = 3
  • Level 3: Nodes = [5, 4] → Rightmost = 4

So the final right view is [1, 3, 4].

Step 4: Store the result

As we detect the rightmost node at each level, we append it to a result list. After processing all levels, we return this list as our right view.

Edge Cases

Case 1: Tree is empty

If the binary tree has no nodes, then there is nothing to view. The right view is simply an empty list: [].

Case 2: Tree has only one node

When the tree contains just a single root node, that node is by default the right view. Example: [1] → Right view: [1].

Case 3: Tree is right skewed

If every node has only a right child, the entire tree is visible from the right. Example: [1, null, 2, null, 3] → Right view: [1, 2, 3].

Case 4: Tree is left skewed

Even though the nodes are on the left, each level has only one node, making it the rightmost by default. Example: [1, 2, null, 3] → Right view: [1, 2, 3].

Case 5: Tree has both left and right children

This is the general case where our logic must correctly select the last node from each level during traversal. The method we implemented ensures this behavior.

Finally

The key idea is to visit the tree level by level and pick the last node at each level. This last node is what you would see from the right. By using a queue and simple bookkeeping, we can ensure the solution works for skewed trees, balanced trees, and even empty trees.

This problem is a great introduction to BFS traversal and thinking about trees from different perspectives. Once you understand level-order traversal, the rest of the solution becomes very intuitive!

  1. Given a binary tree, if the tree is empty, return an empty result.
  2. Initialize a queue and enqueue the root node.
  3. While the queue is not empty, determine the number of nodes at the current level (levelSize).
  4. For each node in the current level, dequeue a node.
  5. If the node is the last one in the level (i.e. for index i == levelSize - 1), record its value as part of the right view.
  6. Enqueue the left and then right child of the node (if they exist) for processing in the next level.
  7. Repeat until all levels are processed; the recorded values form the right view of the binary tree.

Implementation and efficiency

C implementation

#include <stdio.h>
#include <stdlib.h>

typedef struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;

TreeNode* createNode(int val) {
    TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
    node->val = val;
    node->left = node->right = NULL;
    return node;
}

int* rightSideView(TreeNode* root, int* returnSize) {
    if (!root) {
        *returnSize = 0;
        return NULL;
    }
    int* result = malloc(100 * sizeof(int));
    TreeNode** queue = malloc(100 * sizeof(TreeNode*));
    int front = 0, rear = 0, resIndex = 0;
    queue[rear++] = root;
    while (front < rear) {
        int levelSize = rear - front;
        for (int i = 0; i < levelSize; i++) {
            TreeNode* node = queue[front++];
            if (i == levelSize - 1)
                result[resIndex++] = node->val;
            if (node->left) queue[rear++] = node->left;
            if (node->right) queue[rear++] = node->right;
        }
    }
    *returnSize = resIndex;
    free(queue);
    return result;
}

int main() {
    TreeNode* root = createNode(1);
    root->left = createNode(2);
    root->right = createNode(3);
    root->left->right = createNode(5);
    root->right->right = createNode(4);
    int size;
    int* view = rightSideView(root, &size);
    printf("Right view: ");
    for (int i = 0; i < size; i++) printf("%d ", view[i]);
    printf("\n");
    free(view);
    return 0;
}

C++ implementation

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x): val(x), left(nullptr), right(nullptr) {}
};

vector<int> rightSideView(TreeNode* root) {
    vector<int> result;
    if (!root) return result;
    queue<TreeNode*> q;
    q.push(root);
    while (!q.empty()) {
        int levelSize = q.size();
        for (int i = 0; i < levelSize; i++) {
            TreeNode* node = q.front(); q.pop();
            if (i == levelSize - 1)
                result.push_back(node->val);
            if (node->left) q.push(node->left);
            if (node->right) q.push(node->right);
        }
    }
    return result;
}

int main() {
    TreeNode* root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->left->right = new TreeNode(5);
    root->right->right = new TreeNode(4);
    vector<int> view = rightSideView(root);
    cout << "Right view: ";
    for (int v : view) cout << v << " ";
    cout << endl;
    return 0;
}

Python implementation

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def rightView(root):
    if not root:
        return []
    result = []
    queue = [root]
    while queue:
        levelSize = len(queue)
        for i in range(levelSize):
            node = queue.pop(0)
            if i == levelSize - 1:
                result.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
    return result

if __name__ == '__main__':
    root = TreeNode(1, TreeNode(2, None, TreeNode(5)), TreeNode(3, None, TreeNode(4)))
    print(rightView(root))

Java implementation

import java.util.*;

class TreeNode {
    int val;
    TreeNode left, right;
    TreeNode(int x) { val = x; }
}

public class RightViewBinaryTree {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        if (root == null) return result;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            int levelSize = queue.size();
            for (int i = 0; i < levelSize; i++) {
                TreeNode node = queue.poll();
                if (i == levelSize - 1)
                    result.add(node.val);
                if (node.left != null) queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }
        }
        return result;
    }

    public static void main(String[] args) {
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        root.left.right = new TreeNode(5);
        root.right.right = new TreeNode(4);
        RightViewBinaryTree sol = new RightViewBinaryTree();
        System.out.println(sol.rightSideView(root));
    }
}

JavaScript implementation

class TreeNode {
    constructor(val, left = null, right = null) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

function rightView(root) {
    if (!root) return [];
    const result = [];
    const queue = [root];
    while (queue.length) {
        const levelSize = queue.length;
        for (let i = 0; i < levelSize; i++) {
            const node = queue.shift();
            if (i === levelSize - 1) result.push(node.val);
            if (node.left) queue.push(node.left);
            if (node.right) queue.push(node.right);
        }
    }
    return result;
}

const root = new TreeNode(1, new TreeNode(2, null, new TreeNode(5)), new TreeNode(3, null, new TreeNode(4)));
console.log(rightView(root));

Go implementation

package main

import (
    "fmt"
)

type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}

func rightSideView(root *TreeNode) []int {
    if root == nil {
        return nil
    }
    result := []int{}
    queue := []*TreeNode{root}
    for len(queue) > 0 {
        size := len(queue)
        for i := 0; i < size; i++ {
            node := queue[0]
            queue = queue[1:]
            if i == size-1 {
                result = append(result, node.Val)
            }
            if node.Left != nil {
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
                queue = append(queue, node.Right)
            }
        }
    }
    return result
}

func main() {
    root := &TreeNode{1, &TreeNode{2, nil, &TreeNode{5, nil, nil}}, &TreeNode{3, nil, &TreeNode{4, nil, nil}}}
    fmt.Println(rightSideView(root))
}

Rust implementation

use std::collections::VecDeque;

#[derive(Debug)]
struct TreeNode {
    val: i32,
    left: Option<Box<TreeNode>>,
    right: Option<Box<TreeNode>>,
}

impl TreeNode {
    fn new(val: i32) -> Self {
        TreeNode { val, left: None, right: None }
    }
}

fn right_view(root: Option<Box<TreeNode>>) -> Vec<i32> {
    let mut result = Vec::new();
    if root.is_none() {
        return result;
    }
    let mut queue = VecDeque::new();
    queue.push_back(root);
    while !queue.is_empty() {
        let level_size = queue.len();
        for i in 0..level_size {
            if let Some(Some(node)) = queue.pop_front() {
                if i == level_size - 1 {
                    result.push(node.val);
                }
                if node.left.is_some() {
                    queue.push_back(node.left);
                }
                if node.right.is_some() {
                    queue.push_back(node.right);
                }
            }
        }
    }
    result
}

fn main() {
    let root = Some(Box::new(TreeNode {
        val: 1,
        left: Some(Box::new(TreeNode {
            val: 2,
            left: None,
            right: Some(Box::new(TreeNode::new(5))),
        })),
        right: Some(Box::new(TreeNode {
            val: 3,
            left: None,
            right: Some(Box::new(TreeNode::new(4))),
        })),
    }));
    println!("{:?}", right_view(root));
}

Kotlin implementation

import java.util.*

class TreeNode(val `val`: Int) {
    var left: TreeNode? = null
    var right: TreeNode? = null
}

fun rightSideView(root: TreeNode?): List<Int> {
    val result = mutableListOf<Int>()
    if (root == null) return result
    val queue: Queue<TreeNode> = LinkedList()
    queue.add(root)
    while (queue.isNotEmpty()) {
        val size = queue.size
        for (i in 0 until size) {
            val node = queue.poll()
            if (i == size - 1) result.add(node.`val`)
            node.left?.let { queue.add(it) }
            node.right?.let { queue.add(it) }
        }
    }
    return result
}

fun main() {
    val root = TreeNode(1)
    root.left = TreeNode(2)
    root.left?.right = TreeNode(5)
    root.right = TreeNode(3)
    root.right?.right = TreeNode(4)
    println(rightSideView(root))
}

TypeScript implementation

class TreeNode {
    val: number;
    left: TreeNode | null;
    right: TreeNode | null;
    constructor(val: number, left: TreeNode | null = null, right: TreeNode | null = null) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

function rightView(root: TreeNode | null): number[] {
    if (!root) return [];
    const result: number[] = [];
    const queue: TreeNode[] = [root];
    while (queue.length) {
        const levelSize = queue.length;
        for (let i = 0; i < levelSize; i++) {
            const node = queue.shift()!;
            if (i === levelSize - 1) result.push(node.val);
            if (node.left) queue.push(node.left);
            if (node.right) queue.push(node.right);
        }
    }
    return result;
}

const root = new TreeNode(1, new TreeNode(2, null, new TreeNode(5)), new TreeNode(3, null, new TreeNode(4)));
console.log(rightView(root));