BFS Level Order Traversal with Direction Toggle (Queue + Deque)
| LeetCode #103 | Difficulty: Medium |
Intuition
The zigzag traversal is very similar to a normal level order traversal (BFS) of a binary tree.
The only difference is that the direction of traversal alternates for each level:
- Level 0 → Left to Right
- Level 1 → Right to Left
- Level 2 → Left to Right
- …
So instead of changing how we traverse the tree, we can simply change how we store the values of each level.
A boolean flag can help track whether the current level should be processed left-to-right or right-to-left.
Approach
- Handle edge case
- If the root is
nullptr, return an empty result.
- If the root is
- Use BFS (Queue) for level traversal
- Push the root node into a queue.
- Process nodes level by level.
- Track traversal direction
- Maintain a boolean
is_order_left. - If
true, store values normally. - If
false, store values in reverse order.
- Maintain a boolean
- Process each level
- Record the current queue size (number of nodes in that level).
- For each node:
- Pop it from the queue.
- If traversal is left-to-right → append value to vector.
- Otherwise → push value to the front of a deque.
- Convert reversed order
- If the level was processed right-to-left, copy elements from the deque to the vector.
- Push the level result
- Add the vector to the final result.
- Toggle the direction flag.
- Continue until queue becomes empty
This ensures every level is processed once while alternating the direction of value storage.
Complexity
-
Time complexity: \(O(n)\)
Each node in the tree is visited exactly once.
-
Space complexity: \(O(n)\)
In the worst case, the queue may store all nodes of the largest level of the tree.
Code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> result;
if(!root) return result;
queue<TreeNode*> nodeQ;
bool is_order_left = true;
nodeQ.push(root);
while(!nodeQ.empty()) {
int sizeQ = nodeQ.size();
vector<int> v;
deque<int> dq;
for(int i=0; i<sizeQ; i++) {
TreeNode* node = nodeQ.front();
nodeQ.pop();
if(is_order_left) {
v.push_back(node->val);
} else {
dq.push_front(node->val);
}
if(node->left) nodeQ.push(node->left);
if(node->right) nodeQ.push(node->right);
}
if(!is_order_left) {
v.assign(dq.begin(), dq.end());
}
result.push_back(v);
is_order_left = !is_order_left;
}
return result;
}
};
Clean BFS with Direct Index Placement (No Deque Needed)
Intuition
The problem is a variation of normal level order traversal (BFS) of a binary tree. The only difference is that the direction alternates at each level.
Instead of reversing a vector or using a deque, we can place elements directly in their correct positions while processing the level.
If the traversal direction is reversed, we simply calculate the correct index for each element.
Approach
-
If the tree is empty, return an empty result.
-
Use a queue to perform BFS traversal.
-
Maintain a boolean
leftToRightto track traversal direction. - For each level:
- Get the current queue size.
- Create a vector of that size.
- Process each node in the level.
- Determine the index for insertion:
- If
leftToRight→index = i - Otherwise →
index = size - 1 - i
- If
-
Insert node values directly into the correct index.
-
Push children into the queue.
- After finishing the level, toggle the direction.
Complexity
-
Time complexity: \(O(n)\)
Each node is visited exactly once.
-
Space complexity: \(O(n)\)
The queue stores nodes of the largest level of the tree.
Code
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> result;
if(!root) return result;
queue<TreeNode*> q;
q.push(root);
bool leftToRight = true;
while(!q.empty()) {
int size = q.size();
vector<int> level(size);
for(int i = 0; i < size; i++) {
TreeNode* node = q.front();
q.pop();
int index = leftToRight ? i : size - 1 - i;
level[index] = node->val;
if(node->left) q.push(node->left);
if(node->right) q.push(node->right);
}
result.push_back(level);
leftToRight = !leftToRight;
}
return result;
}
};