Skip to content

Commit bf8b3ac

Browse files
authored
Create README.md
1 parent 75a8413 commit bf8b3ac

File tree

1 file changed

+275
-0
lines changed
  • 17 - Binary Tree Data Structure Problems/13 - Binary Tree Zigzag Level Order Traversal

1 file changed

+275
-0
lines changed
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
<h1 align='center'>Binary - Tree - Zigzag - Level - Order - Traversal</h1>
2+
3+
## Problem Statement
4+
5+
**Problem URL :** [Binary Tree Zigzag Level Order Traversal](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/)
6+
7+
![image](https://github.com/user-attachments/assets/fdbcc5c4-6cc6-4693-8313-6da999c76e2a)
8+
![image](https://github.com/user-attachments/assets/6492f8a5-00b5-4ad9-a4a2-af280a442505)
9+
10+
## Problem Explanation
11+
In this problem, we are given a binary tree and asked to return its level-order traversal in a zigzag pattern. A zigzag pattern means:
12+
- Traverse the first level from left to right.
13+
- Traverse the second level from right to left.
14+
- Continue alternating directions for each level.
15+
16+
#### Example:
17+
Consider this binary tree:
18+
```
19+
1
20+
/ \
21+
2 3
22+
/ \ \
23+
4 5 6
24+
```
25+
26+
The expected zigzag level-order traversal is:
27+
```
28+
[
29+
[1],
30+
[3, 2],
31+
[4, 5, 6]
32+
]
33+
```
34+
35+
Here:
36+
- Level 1: Traverse left-to-right → `[1]`
37+
- Level 2: Traverse right-to-left → `[3, 2]`
38+
- Level 3: Traverse left-to-right again → `[4, 5, 6]`
39+
40+
### Step 2: Approach
41+
To solve this, we’ll use a **Breadth-First Search (BFS)** approach with a **queue** to process each level:
42+
1. Start by adding the root node to the queue.
43+
2. Process each level of the tree in the queue until all nodes are covered:
44+
- For each level, we store nodes in a `vector<int> ans` where `ans` holds the values of nodes in the current level.
45+
- For left-to-right order, add nodes directly in the order they appear in the queue.
46+
- For right-to-left order, add nodes in reverse order.
47+
3. Alternate the direction (left-to-right or right-to-left) for each level by using a boolean flag `LTR` (Left to Right).
48+
4. Append each `ans` vector to the `result` vector at the end of processing each level.
49+
50+
## Problem Solution
51+
```cpp
52+
class Solution {
53+
public:
54+
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
55+
vector<vector<int>> result; // Stores the final zigzag level order traversal.
56+
if(root == NULL) return result; // If the root is NULL, return an empty result.
57+
58+
queue<TreeNode*> q; // Queue to hold nodes to be processed in BFS manner.
59+
q.push(root); // Start with the root node in the queue.
60+
61+
bool LTR = true; // Left-To-Right flag; toggles direction for each level.
62+
63+
while(!q.empty()){
64+
int size = q.size(); // Number of nodes at the current level.
65+
vector<int> ans(size); // Vector to store current level's node values.
66+
67+
for(int i = 0; i < size; i++){
68+
TreeNode* frontNode = q.front(); // Take the front node from the queue.
69+
q.pop(); // Remove it from the queue.
70+
71+
// Determine the index based on the current traversal direction:
72+
int index = LTR ? i : size - i - 1;
73+
ans[index] = frontNode->val; // Store node's value in ans at the calculated index.
74+
75+
// Add child nodes to the queue for processing in the next level.
76+
if(frontNode->left) q.push(frontNode->left);
77+
if(frontNode->right) q.push(frontNode->right);
78+
}
79+
80+
LTR = !LTR; // Toggle direction for the next level.
81+
result.push_back(ans); // Add the current level's result to the final output.
82+
}
83+
84+
return result; // Return the zigzag level-order traversal.
85+
}
86+
};
87+
```
88+
89+
## Problem Solution Explanation
90+
Here’s the code with an explanation:
91+
92+
```cpp
93+
class Solution {
94+
public:
95+
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
96+
```
97+
- **Line 1-2**: Defines a class `Solution` with a public method `zigzagLevelOrder` that takes a pointer to the root of a binary tree (`TreeNode* root`) and returns a 2D vector of integers (`vector<vector<int>>`), which will hold the zigzag level order traversal of the tree.
98+
99+
```cpp
100+
vector<vector<int>> result; // Stores the final zigzag level order traversal.
101+
```
102+
- **Line 3**: Initializes a 2D vector `result` to hold the final output of the zigzag traversal.
103+
104+
### Example:
105+
- If the input tree is:
106+
```
107+
1
108+
/ \
109+
2 3
110+
```
111+
- Initially, `result` is empty: `result = []`.
112+
113+
```cpp
114+
if(root == NULL) return result; // If the root is NULL, return an empty result.
115+
```
116+
- **Line 4**: Checks if the `root` is `NULL` (i.e., the tree is empty). If it is, the function immediately returns the empty `result`.
117+
118+
### Example:
119+
- For an empty tree (`root = NULL`), the output is: `result = []`.
120+
121+
```cpp
122+
queue<TreeNode*> q; // Queue to hold nodes to be processed in BFS manner.
123+
q.push(root); // Start with the root node in the queue.
124+
```
125+
- **Lines 5-6**: Initializes a queue `q` to hold `TreeNode` pointers. The root node is added to the queue for processing.
126+
127+
### Example:
128+
- For the tree:
129+
```
130+
1
131+
/ \
132+
2 3
133+
```
134+
- After these lines, the queue will contain: `q = [1]`.
135+
136+
```cpp
137+
bool LTR = true; // Left-To-Right flag; toggles direction for each level.
138+
```
139+
- **Line 7**: Initializes a boolean variable `LTR` to indicate the current traversal direction. It starts with `true`, meaning the first level will be traversed from left to right.
140+
141+
### Example:
142+
- At the start, `LTR = true`.
143+
144+
```cpp
145+
while(!q.empty()){
146+
```
147+
- **Line 8**: Enters a loop that continues as long as there are nodes in the queue (`q` is not empty).
148+
149+
### Example:
150+
- Initially, `q = [1]`, so we enter the loop.
151+
152+
```cpp
153+
int size = q.size(); // Number of nodes at the current level.
154+
vector<int> ans(size); // Vector to store current level's node values.
155+
```
156+
- **Lines 9-10**: Calculates the number of nodes at the current level (`size`) and initializes a vector `ans` of that size to hold the values of nodes at the current level.
157+
158+
### Example:
159+
- At the first iteration, `size = 1` (only node `1`), so `ans` is initialized as: `ans = [0]`.
160+
161+
```cpp
162+
for(int i = 0; i < size; i++){
163+
```
164+
- **Line 11**: Starts a loop that will iterate over each node at the current level.
165+
166+
### Example:
167+
- For the first level with one node, `i` will take the value `0`.
168+
169+
```cpp
170+
TreeNode* frontNode = q.front(); // Take the front node from the queue.
171+
q.pop(); // Remove it from the queue.
172+
```
173+
- **Lines 12-13**: Retrieves the front node from the queue (the one to be processed) and then removes it from the queue.
174+
175+
### Example:
176+
- For the first iteration, `frontNode` is `1`, so after these lines, `q` will be empty: `q = []`.
177+
178+
```cpp
179+
// Determine the index based on the current traversal direction:
180+
int index = LTR ? i : size - i - 1;
181+
```
182+
- **Line 14**: Calculates the index where the node's value should be placed in the `ans` vector based on the traversal direction:
183+
- If `LTR` is `true`, use the current index `i`.
184+
- If `LTR` is `false`, calculate the index as `size - i - 1` (to fill in reverse order).
185+
186+
### Example:
187+
- Since `LTR = true`, for the first iteration (`i = 0`), `index = 0`.
188+
189+
```cpp
190+
ans[index] = frontNode->val; // Store node's value in ans at the calculated index.
191+
```
192+
- **Line 15**: Assigns the value of `frontNode` (the current node) to the `ans` vector at the calculated index.
193+
194+
### Example:
195+
- After this line, `ans` is updated to: `ans = [1]`.
196+
197+
```cpp
198+
// Add child nodes to the queue for processing in the next level.
199+
if(frontNode->left) q.push(frontNode->left);
200+
if(frontNode->right) q.push(frontNode->right);
201+
```
202+
- **Lines 16-18**: Checks if the current node has left or right children. If they exist, they are added to the queue for processing in the next level.
203+
204+
### Example:
205+
- The current node (`1`) has children (`2` and `3`), so the queue will be updated to: `q = [2, 3]`.
206+
207+
```cpp
208+
LTR = !LTR; // Toggle direction for the next level.
209+
```
210+
- **Line 19**: Toggles the value of `LTR`. If it was `true`, it becomes `false`, and vice versa. This ensures the next level will be processed in the opposite order.
211+
212+
### Example:
213+
- After processing the first level, `LTR` is toggled to `false`.
214+
215+
```cpp
216+
result.push_back(ans); // Add the current level's result to the final output.
217+
```
218+
- **Line 20**: Appends the current `ans` vector (which holds values for the current level) to the `result` vector.
219+
220+
### Example:
221+
- After the first level, `result` is updated to: `result = [[1]]`.
222+
223+
```cpp
224+
return result; // Return the zigzag level-order traversal.
225+
```
226+
- **Line 21**: After all levels have been processed, returns the `result` vector containing the zigzag level order traversal.
227+
228+
### Full Example Walkthrough:
229+
Now let’s consider a complete example of the binary tree and see how the code works step by step:
230+
231+
Given the binary tree:
232+
```
233+
1
234+
/ \
235+
2 3
236+
/ \ \
237+
4 5 6
238+
```
239+
240+
1. **First Level**: `LTR = true`
241+
- Queue: `[1]`
242+
- Process node `1`: `ans = [1]`
243+
- Children added to queue: `[2, 3]`
244+
- Result after this level: `[[1]]`
245+
246+
2. **Second Level**: `LTR = false`
247+
- Queue: `[2, 3]`
248+
- Process node `2`: `ans = [0, 2]` (index `1`)
249+
- Process node `3`: `ans = [3, 2]` (index `0`)
250+
- Children added to queue: `[4, 5, 6]`
251+
- Result after this level: `[[1], [3, 2]]`
252+
253+
3. **Third Level**: `LTR = true`
254+
- Queue: `[4, 5, 6]`
255+
- Process node `4`: `ans = [4, 0, 0]` (index `0`)
256+
- Process node `5`: `ans = [4, 5, 0]` (index `1`)
257+
- Process node `6`: `ans = [4, 5, 6]` (index `2`)
258+
- Queue becomes empty after this level.
259+
- Result after this level: `[[1], [3, 2], [4, 5, 6]]`
260+
261+
Final output will be:
262+
```cpp
263+
[
264+
[1],
265+
[3, 2],
266+
[4, 5, 6]
267+
]
268+
```
269+
270+
### Time and Space Complexity Analysis
271+
272+
- **Time Complexity**: \(O(N)\), where \(N\) is the total number of nodes in the tree. Each node is processed once as we perform BFS traversal, visiting every level and node.
273+
- **Space Complexity**: \(O(N)\) for storing the nodes in the queue and the result array. The queue at most holds nodes of one level, which could be up to \(N/2\) nodes for the last level in a full binary tree.
274+
275+
This solution is efficient for handling typical binary tree structures, even for larger trees, due to its linear complexity in both time and space.

0 commit comments

Comments
 (0)