BFS (Level Order) traverses a tree level by level, processing all nodes at the same depth before moving deeper.
Its core advantage:
BFS guarantees the shortest path in unweighted trees and enables level-aware problems.
Focus on recognizing:
“Level by level” + “Queue” + “Breadth” = BFS / Level Order
Pattern Table
| Pattern | Typical Questions | Trigger |
|---|---|---|
| Level Order | Return levels as lists | Queue + size batching |
| Right/Left View | See first node at each level | Track first/last in level |
| Zigzag | Alternating left-right | Toggle direction per level |
Mental Trigger
Queue → Process level size → Add children → Repeat.
1. Generic Java BFS Template (Base)
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
if (root == null) return result;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
List<Integer> level = new ArrayList<>();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
level.add(node.val);
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
result.add(level);
}
return result;
}from collections import deque
def level_order(root):
result = []
if root is None:
return result
queue = deque([root])
while queue:
size = len(queue)
level = []
for _ in range(size):
node = queue.popleft()
level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(level)
return resultvector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> result;
if (root == nullptr) return result;
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
int size = q.size();
vector<int> level;
for (int i = 0; i < size; i++) {
TreeNode* node = q.front();
q.pop();
level.push_back(node->val);
if (node->left != nullptr) q.push(node->left);
if (node->right != nullptr) q.push(node->right);
}
result.push_back(level);
}
return result;
}function levelOrder(root) {
const result = [];
if (root === null) return result;
const queue = [root];
while (queue.length > 0) {
const size = queue.length;
const level = [];
for (let i = 0; i < size; i++) {
const node = queue.shift();
level.push(node.val);
if (node.left !== null) queue.push(node.left);
if (node.right !== null) queue.push(node.right);
}
result.push(level);
}
return result;
}Everything else in Level Order is just a modification of this template.
Pattern 1: Right Side View
Last node dequeued per level = what you see from the right. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Right Side View
Return the last node visible on each level when the tree is viewed from the right.
BFS level by level using a queue; the final node dequeued in each level is exactly the rightmost node. No depth-tracking DFS needed.
1
queue = [root]
2
while queue:
3
size = len(queue) // level marker
4
for i in 0..size-1:
5
n = dequeue; if i == size-1 → visible
6
enqueue children
Java Code
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 size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
if (i == size - 1)
result.add(node.val);
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}
return result;
}def right_side_view(root):
result = []
if root is None:
return result
queue = deque([root])
while queue:
size = len(queue)
for i in range(size):
node = queue.popleft()
if i == size - 1:
result.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return resultvector<int> rightSideView(TreeNode* root) {
vector<int> result;
if (root == nullptr) return result;
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
TreeNode* node = q.front();
q.pop();
if (i == size - 1)
result.push_back(node->val);
if (node->left != nullptr) q.push(node->left);
if (node->right != nullptr) q.push(node->right);
}
}
return result;
}function rightSideView(root) {
const result = [];
if (root === null) return result;
const queue = [root];
while (queue.length > 0) {
const size = queue.length;
for (let i = 0; i < size; i++) {
const node = queue.shift();
if (i === size - 1)
result.push(node.val);
if (node.left !== null) queue.push(node.left);
if (node.right !== null) queue.push(node.right);
}
}
return result;
}What Changed from the Base Template?
Track last node in each level
Base:
level.add(node.val); // add all nodes
Changed:
if (i == size - 1)
result.add(node.val); // only add last node of level
because the right side view is the last (rightmost) node at each level.
Right Side View = Level Order + Add last node of each level.
Pattern 2: Zigzag Level Order
Same level BFS with a direction flag that flips each row. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Zigzag Level Order
Return tree values level by level, alternating left-to-right and right-to-left each row.
Standard BFS collects each level, then reverse the level when the direction flag is false and toggle it. Same skeleton as right-side view — only the per-level bookkeeping differs.
1
BFS by levels
2
leftToRight = true
3
collect level values
4
if !leftToRight: reverse(level)
5
toggle direction
Java Code
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
if (root == null) return result;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
boolean leftToRight = true;
while (!queue.isEmpty()) {
int size = queue.size();
LinkedList<Integer> level = new LinkedList<>();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
if (leftToRight)
level.addLast(node.val);
else
level.addFirst(node.val);
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
result.add(level);
leftToRight = !leftToRight;
}
return result;
}def zigzag_level_order(root):
result = []
if root is None:
return result
queue = deque([root])
left_to_right = True
while queue:
size = len(queue)
level = deque()
for _ in range(size):
node = queue.popleft()
if left_to_right:
level.append(node.val)
else:
level.appendleft(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(list(level))
left_to_right = not left_to_right
return resultvector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> result;
if (root == nullptr) return result;
queue<TreeNode*> q;
q.push(root);
bool leftToRight = true;
while (!q.empty()) {
int size = q.size();
deque<int> level;
for (int i = 0; i < size; i++) {
TreeNode* node = q.front();
q.pop();
if (leftToRight)
level.push_back(node->val);
else
level.push_front(node->val);
if (node->left != nullptr) q.push(node->left);
if (node->right != nullptr) q.push(node->right);
}
result.push_back(vector<int>(level.begin(), level.end()));
leftToRight = !leftToRight;
}
return result;
}function zigzagLevelOrder(root) {
const result = [];
if (root === null) return result;
const queue = [root];
let leftToRight = true;
while (queue.length > 0) {
const size = queue.length;
const level = [];
for (let i = 0; i < size; i++) {
const node = queue.shift();
if (leftToRight)
level.push(node.val);
else
level.unshift(node.val);
if (node.left !== null) queue.push(node.left);
if (node.right !== null) queue.push(node.right);
}
result.push(level);
leftToRight = !leftToRight;
}
return result;
}What Changed from the Base Template?
Toggle direction
Added:
boolean leftToRight = true;
// toggle each level
leftToRight = !leftToRight;
because zigzag alternates direction every level.
AddFirst or AddLast
Base:
level.add(node.val);
Changed:
if (leftToRight) level.addLast(node.val);
else level.addFirst(node.val);
to reverse the order of nodes in the level when going right-to-left.
Zigzag = Level Order + Toggle direction + AddFirst for reverse levels.
BFS Pattern Evolution
Base Level Order (queue + size batching)
↓
Right Side View
(+ last node of each level)
↓
Zigzag
(+ toggle direction + addFirst/addLast)
Common Mistakes
Not saving queue.size() before the inner loop.
The size changes as children are added — capture it once at the start.
Forgetting null check.
Always if (root == null) return before creating the queue.
Using poll on empty queue.
Check !queue.isEmpty() before polling.
Recognition Cheat Sheet
| If you see… | Think… |
|---|---|
| Level-by-level output | BFS with size batching |
| Right/left view of tree | BFS + track last/first in level |
| Zigzag / spiral order | BFS + toggle direction |
| Minimum depth | BFS + return when leaf found |
Premium Content
Unlock BFS & Level Order and all premium lessons with a subscription.
From ₹199.99/year — See plans