🧠
Brute Force (DFS with Level Tracking and Overwriting)
💡 This approach uses a simple depth-first search to explore all nodes, keeping track of the level and overwriting the value for each level to ensure the rightmost node is recorded. It helps beginners understand the problem by directly simulating the view from the right side.
Intuition
Traverse the tree depth-first, and for each level, overwrite the stored value with the current node's value. Because DFS explores right before left, the last node visited at each level will be the rightmost node.
Algorithm
- Initialize a list to store the rightmost node value at each level.
- Perform DFS starting from root with level 0.
- At each node, overwrite the value at the current level in the list.
- After traversal, return the list containing rightmost nodes per level.
💡 The key difficulty is realizing that overwriting values at each level during DFS ensures the rightmost node is recorded, even though we visit right children first.
from typing import Optional, List
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def rightSideView(root: Optional[TreeNode]) -> List[int]:
rightmost_value_at_depth = []
def dfs(node, depth):
if not node:
return
if depth == len(rightmost_value_at_depth):
rightmost_value_at_depth.append(node.val)
else:
rightmost_value_at_depth[depth] = node.val
dfs(node.right, depth + 1)
dfs(node.left, depth + 1)
dfs(root, 0)
return rightmost_value_at_depth
# Example usage:
# Construct tree [1,2,3,null,5,null,4]
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.right = TreeNode(5)
root.right.right = TreeNode(4)
print(rightSideView(root)) # Output: [1,3,4]
Line Notes
def rightSideView(root: Optional[TreeNode]) -> List[int]:Defines the main function with type hints for clarity
rightmost_value_at_depth = []Stores the rightmost node value at each depth level
def dfs(node, depth):Helper function to perform DFS with current node and depth
if not node:Base case: if node is None, stop recursion
if depth == len(rightmost_value_at_depth):If first time visiting this depth, append node value
rightmost_value_at_depth[depth] = node.valOverwrite existing value to keep rightmost node at this depth
dfs(node.right, depth + 1)Traverse right subtree first to ensure rightmost nodes overwrite left
dfs(node.left, depth + 1)Traverse left subtree after right
dfs(root, 0)Start DFS from root at depth 0
return rightmost_value_at_depthReturn the collected rightmost nodes per level
import java.util.*;
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int val) { this.val = val; }
}
public class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> rightmostValueAtDepth = new ArrayList<>();
dfs(root, 0, rightmostValueAtDepth);
return rightmostValueAtDepth;
}
private void dfs(TreeNode node, int depth, List<Integer> rightmostValueAtDepth) {
if (node == null) return;
if (depth == rightmostValueAtDepth.size()) {
rightmostValueAtDepth.add(node.val);
} else {
rightmostValueAtDepth.set(depth, node.val);
}
dfs(node.right, depth + 1, rightmostValueAtDepth);
dfs(node.left, depth + 1, rightmostValueAtDepth);
}
// Example main method
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);
Solution sol = new Solution();
System.out.println(sol.rightSideView(root)); // Output: [1, 3, 4]
}
}
Line Notes
public List<Integer> rightSideView(TreeNode root)Main method signature returning list of rightmost nodes
List<Integer> rightmostValueAtDepth = new ArrayList<>();Stores rightmost node values per depth
if (node == null) return;Base case for recursion
if (depth == rightmostValueAtDepth.size())If first time at this depth, add node value
rightmostValueAtDepth.set(depth, node.val);Overwrite to keep rightmost node at this depth
dfs(node.right, depth + 1, rightmostValueAtDepth);Traverse right subtree first to ensure rightmost nodes overwrite left
dfs(node.left, depth + 1, rightmostValueAtDepth);Traverse left subtree after right
public static void main(String[] args)Driver code to test the solution
#include <iostream>
#include <vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left, *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
vector<int> rightmostValueAtDepth;
dfs(root, 0, rightmostValueAtDepth);
return rightmostValueAtDepth;
}
private:
void dfs(TreeNode* node, int depth, vector<int>& rightmostValueAtDepth) {
if (!node) return;
if (depth == rightmostValueAtDepth.size()) {
rightmostValueAtDepth.push_back(node->val);
} else {
rightmostValueAtDepth[depth] = node->val;
}
dfs(node->right, depth + 1, rightmostValueAtDepth);
dfs(node->left, depth + 1, rightmostValueAtDepth);
}
};
// Example usage
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);
Solution sol;
vector<int> res = sol.rightSideView(root);
for (int v : res) cout << v << " "; // Output: 1 3 4
cout << endl;
return 0;
}
Line Notes
vector<int> rightmostValueAtDepth;Stores rightmost node values per depth
if (!node) return;Base case to stop recursion
if (depth == rightmostValueAtDepth.size())First time visiting this depth, add node value
rightmostValueAtDepth[depth] = node->val;Overwrite to keep rightmost node at this depth
dfs(node->right, depth + 1, rightmostValueAtDepth);Traverse right subtree first to ensure rightmost nodes overwrite left
dfs(node->left, depth + 1, rightmostValueAtDepth);Traverse left subtree after right
int main()Driver code to test the solution
for (int v : res) cout << v << " ";Print the right side view nodes
function TreeNode(val, left = null, right = null) {
this.val = val;
this.left = left;
this.right = right;
}
function rightSideView(root) {
const rightmostValueAtDepth = [];
function dfs(node, depth) {
if (!node) return;
if (depth === rightmostValueAtDepth.length) {
rightmostValueAtDepth.push(node.val);
} else {
rightmostValueAtDepth[depth] = node.val;
}
dfs(node.right, depth + 1);
dfs(node.left, depth + 1);
}
dfs(root, 0);
return rightmostValueAtDepth;
}
// Example usage:
const 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);
console.log(rightSideView(root)); // Output: [1, 3, 4]
Line Notes
function rightSideView(root)Main function to compute right side view
const rightmostValueAtDepth = [];Stores rightmost node values per depth
if (!node) return;Base case to stop recursion
if (depth === rightmostValueAtDepth.length)First time visiting this depth, add node value
rightmostValueAtDepth[depth] = node.val;Overwrite to keep rightmost node at this depth
dfs(node.right, depth + 1);Traverse right subtree first to ensure rightmost nodes overwrite left
dfs(node.left, depth + 1);Traverse left subtree after right
console.log(rightSideView(root));Print the right side view nodes
We visit each node once, so time is O(n). The recursion stack can go as deep as the tree height h, so space is O(h).
💡 For a tree with 1000 nodes and height 10, this means about 1000 operations and stack depth up to 10.
Interview Verdict: Accepted
This approach is accepted but can be improved for clarity and iterative style.