Skip to content

Commit 9404101

Browse files
authored
Create README.md
1 parent bf8b3ac commit 9404101

File tree

1 file changed

+276
-0
lines changed
  • 17 - Binary Tree Data Structure Problems/14 - Zigzag Tree Traversal

1 file changed

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