Imagine standing to the right of a binary tree and looking left — you see exactly one node per level: the rightmost one. BFS with a level-width snapshot makes it trivial: process each level, grab the last node.
Given the root of a binary tree, return the values visible when viewed from the right side — one value per depth level, the rightmost node at each level.
Concrete example with tree [3, 9, 20, null, null, 15, 7]:
3 ← only node at depth 0 → see 3
/ \
9 20 ← rightmost at depth 1 → see 20
/ \
15 7 ← rightmost at depth 2 → see 7Output: [3, 20, 7].
levelSize = queue.length. Process exactly that many nodes; the node at index levelSize - 1 is the rightmost visible one. Add it to the result. This is a single O(n) pass — no extra memory beyond the queue.root is null, return []. An empty tree has no visible nodes.root into a queue. This is the BFS frontier for depth 0.levelSize = queue.length. This freezes the current level's count before we add children.levelSize nodes. For each, push its left and right children (non-null only) for the next level.i === levelSize - 1, push the node's value to result. That node is rightmost at this depth.result holds one value per depth.0 instead of levelSize - 1.Both solutions are O(n) time. BFS queue holds at most one full level — up to n/2 nodes for a perfect binary tree, so space is O(w). The DFS recursive stack is at most O(h) deep, where h is height — better for wide balanced trees, worse for skewed trees.
levelSize then drain exactly that many" idiom solves Binary Tree Level Order Traversal, Maximum Depth of Binary Tree, Minimum Depth of Binary Tree, Rotting Oranges (multi-source BFS on a grid), and Word Ladder (same level = same edit distance).3. We'll process level by level and record the last node of each level.1function rightSideView(root: TreeNode | null): number[] {2 if (!root) return [];3▶ const result: number[] = [];4▶ const queue: TreeNode[] = [root];56 while (queue.length > 0) {7 const levelSize = queue.length; // snapshot current level width8 for (let i = 0; i < levelSize; i++) {9 const node = queue.shift()!;10 if (i === levelSize - 1) { // last node in this level11 result.push(node.val);12 }13 if (node.left) queue.push(node.left);14 if (node.right) queue.push(node.right);15 }16 }17 return result;18}
function rightSideView(root: TreeNode | null): number[] {
if (!root) return [];
const result: number[] = [];
const queue: TreeNode[] = [root];
while (queue.length > 0) {
const levelSize = queue.length; // snapshot current level width
for (let i = 0; i < levelSize; i++) {
const node = queue.shift()!;
if (i === levelSize - 1) { // last node in this level
result.push(node.val);
}
if (node.left) queue.push(node.left);
if (node.right) queue.push(node.right);
}
}
return result;
}result collects one value per level. The queue starts with just the root — the entire first level.queue.length beforethe inner loop is the crux of the pattern. It captures how many nodes are at the current depth so new children pushed inside the loop don't contaminate the count.for loop processes exactly the snapshotted count. At each step we dequeue, optionally record, and enqueue children. When i === levelSize - 1we're at the rightmost node of this level.while loop empties the queue, every depth has contributed exactly one value to result.result array is O(h) where h is tree height.right subtree before left, and record a node's value only the first time you reach each depth (use a depth parameter and a map).0 instead of levelSize - 1. In DFS, traverse left-first and again record only the first node per depth.if (i === levelSize - 1) result.push(...) with levelArr.push(node.val) and push the sub-array at the end of each level.function rightSideView(root: TreeNode | null): number[] {
if (!root) return [];
const result: number[] = [];
const queue: TreeNode[] = [root];
while (queue.length > 0) {
const levelSize = queue.length; // snapshot current level width
for (let i = 0; i < levelSize; i++) {
const node = queue.shift()!;
if (i === levelSize - 1) { // last node in this level
result.push(node.val);
}
if (node.left) queue.push(node.left);
if (node.right) queue.push(node.right);
}
}
return result;
}result array is O(h) where h is tree height.Compute the height, then for each depth d run a DFS that records every node at that depth and keep only the last one visited (the rightmost, since we recurse right before left).
function rightSideView(root: TreeNode | null): number[] {
function height(node: TreeNode | null): number {
if (node === null) return 0;
return 1 + Math.max(height(node.left), height(node.right));
}
// Visit right subtree first, so the LAST value written for a depth is the rightmost.
function rightmost(node: TreeNode | null, depth: number, slot: { val: number | null }): void {
if (node === null) return;
if (depth === 0) { slot.val = node.val; return; }
rightmost(node.right, depth - 1, slot);
rightmost(node.left, depth - 1, slot);
}
const result: number[] = [];
const h = height(root);
for (let d = 0; d < h; d++) {
const slot: { val: number | null } = { val: null };
rightmost(root, d, slot);
if (slot.val !== null) result.push(slot.val);
}
return result;
}| "visible from the right/left side" | BFS level-order, last/first per level |
| process one depth at a time | snapshot levelSize = queue.length before loop |
| "level order traversal" | BFS with levelSize snapshot, push children |
| tree problem mentioning depth or layer | BFS queue with per-level loop |
function rightSideView(root: TreeNode | null): number[] {
if (!root) return [];
const result: number[] = [];
const queue: TreeNode[] = [root];
while (queue.length > 0) {
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;
}[3, 9, 20, null, null, 15, 7], what does rightSideView return?