Right View of a Binary Tree
Problem and examples
| 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!
- Given a binary tree, if the tree is empty, return an empty result.
- Initialize a
queueand enqueue the root node. - While the queue is not empty, determine the number of nodes at the current level (
levelSize). - For each node in the current level, dequeue a node.
- 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. - Enqueue the left and then right child of the node (if they exist) for processing in the next level.
- 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));