Skip to content

Commit 7d76e27

Browse files
authored
Create README.md
1 parent aa75c52 commit 7d76e27

File tree

1 file changed

+385
-0
lines changed
  • 17 - Binary Tree Data Structure Problems/32 - Buring Tree

1 file changed

+385
-0
lines changed
Lines changed: 385 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,385 @@
1+
<h1 align='center'>Burning - Tree</h1>
2+
3+
## Problem Statement
4+
5+
**Problem URL :** [Burning Tree](https://www.geeksforgeeks.org/problems/burning-tree/1)
6+
7+
![image](https://github.com/user-attachments/assets/e9886a6e-9b0e-4d7c-ab97-0ca74a512c63)
8+
![image](https://github.com/user-attachments/assets/11c685b8-fcf4-4011-bfd6-583b7b509990)
9+
![image](https://github.com/user-attachments/assets/5bd4cb7c-84a0-4c62-8ee0-5a2645a9e0e9)
10+
11+
## Problem Explanation
12+
Let's go through each of the steps in detail to understand and explain the solution to the **Burning Tree** problem on GeeksforGeeks.
13+
14+
---
15+
16+
### Step 1: Problem Statement
17+
18+
**Problem Statement**:
19+
Given a binary tree and a target node, imagine starting a fire at the target node. Every minute, the fire spreads to adjacent nodes (left, right, and parent). We need to calculate the minimum time required for the entire tree to be burnt.
20+
21+
**Example**:
22+
Consider a binary tree:
23+
```
24+
1
25+
/ \
26+
2 3
27+
/ \
28+
4 5
29+
```
30+
If we start the fire at node `2`, then:
31+
- At time `1`, nodes `4` and `5` catch fire.
32+
- At time `2`, nodes `1` and `3` catch fire.
33+
- The entire tree is burnt at time `2`, so the answer is `2`.
34+
35+
**Edge Cases**:
36+
1. If the tree has only one node, the time taken would be `0`.
37+
2. If the target node is a leaf node, then the burn would spread to its parent only in the next time unit.
38+
3. If the tree is unbalanced, the solution must account for nodes at different depths from the target.
39+
40+
---
41+
42+
### Step 2: Approach
43+
44+
**High-Level Overview**:
45+
To solve this problem, we’ll use two main steps:
46+
1. **Identify the Parent of Each Node**: This will help in spreading the fire upwards towards the parent nodes.
47+
2. **Simulate the Burning Process**: Using a breadth-first search (BFS), we can track how fire spreads level by level to adjacent nodes.
48+
49+
**Step-by-Step Breakdown**:
50+
1. **Parent Mapping**:
51+
- Traverse the tree and create a mapping of each node to its parent.
52+
- While creating the parent map, locate the target node in the tree.
53+
54+
2. **Burn Simulation Using BFS**:
55+
- Initialize a queue with the target node and a `visited` set to track nodes that have already caught fire.
56+
- At each time unit (each BFS level), spread the fire to the node’s left, right, and parent (if they haven’t burned yet).
57+
- Count the time units until all nodes have burned.
58+
59+
**Pseudocode**:
60+
```plaintext
61+
Function createParentMapping(root, target):
62+
Initialize queue with root, nodeToParent map, result (target node)
63+
While queue is not empty:
64+
Pop node from queue
65+
If node data equals target, set it as result
66+
For each child of node:
67+
Set node as parent in nodeToParent map
68+
Push child to queue
69+
Return result (target node)
70+
71+
Function burnTree(root, nodeToParent):
72+
Initialize queue with root, visited set, ans as 0
73+
While queue is not empty:
74+
Flag to track if any new node catches fire
75+
For each node in queue:
76+
Spread fire to unvisited neighbors (left, right, parent)
77+
Set flag = true if new node catches fire
78+
If flag is true, increment ans
79+
Return ans
80+
```
81+
82+
## Problem Solution
83+
```cpp
84+
class Solution {
85+
public:
86+
Node* createParentMapping(Node* root, int target, unordered_map<Node*, Node*>&nodeToParent){
87+
Node* result = NULL;
88+
queue<Node*> q;
89+
q.push(root);
90+
91+
nodeToParent[root] = NULL;
92+
93+
while(!q.empty()){
94+
Node* front = q.front();
95+
q.pop();
96+
97+
if(front -> data == target) result = front;
98+
99+
if(front -> left){
100+
nodeToParent[front -> left] = front;
101+
q.push(front -> left);
102+
}
103+
104+
if(front -> right){
105+
nodeToParent[front -> right] = front;
106+
q.push(front -> right);
107+
}
108+
}
109+
110+
return result;
111+
}
112+
113+
int burnTree(Node* root, unordered_map<Node*, Node*> &nodeToParent){
114+
unordered_map<Node*, bool> visited;
115+
queue<Node*> q;
116+
117+
q.push(root);
118+
visited[root] = true;
119+
120+
int ans = 0;
121+
122+
while(!q.empty()){
123+
bool flag = false;
124+
int size = q.size();
125+
126+
for(int i = 0; i < size; i++){
127+
Node* front = q.front();
128+
q.pop();
129+
130+
if(front -> left && !visited[front->left]){
131+
flag = true;
132+
q.push(front -> left);
133+
visited[front -> left] = true;
134+
}
135+
136+
if(front -> right && !visited[front -> right]){
137+
flag = true;
138+
q.push(front -> right);
139+
visited[front -> right] = true;
140+
}
141+
142+
if(nodeToParent[front] && !visited[nodeToParent[front]]){
143+
flag = true;
144+
q.push(nodeToParent[front]);
145+
visited[nodeToParent[front]] = true;
146+
}
147+
}
148+
149+
if(flag == true) ans++;
150+
151+
}
152+
153+
return ans;
154+
}
155+
156+
int minTime(Node* root, int target)
157+
{
158+
unordered_map<Node*, Node*> nodeToParent;
159+
Node* targetNode = createParentMapping(root, target, nodeToParent);
160+
161+
return burnTree(targetNode, nodeToParent);
162+
}
163+
};
164+
```
165+
166+
## Problem Solution Explanation
167+
Let’s go through the code line-by-line, focusing on each function in detail with examples.
168+
169+
The solution consists of three main functions:
170+
171+
1. **`createParentMapping`** - Builds a map of each node to its parent and identifies the target node.
172+
2. **`burnTree`** - Uses BFS to simulate the burning process from the target node.
173+
3. **`minTime`** - Manages the process by calling both `createParentMapping` and `burnTree`.
174+
175+
Let’s go over each function in detail.
176+
177+
#### Function `createParentMapping`
178+
179+
```cpp
180+
Node* createParentMapping(Node* root, int target, unordered_map<Node*, Node*>& nodeToParent) {
181+
Node* result = NULL; // To store the target node once we find it
182+
queue<Node*> q; // Queue for level-order traversal
183+
q.push(root); // Start traversal from the root
184+
nodeToParent[root] = NULL; // Root has no parent, so set it to NULL
185+
```
186+
187+
1. **Explanation**:
188+
- We start with `result` as `NULL`, which will eventually store our target node.
189+
- A `queue` is initialized to perform a level-order traversal of the tree.
190+
- We map the `root` node’s parent as `NULL` since it has no parent.
191+
192+
**Example**:
193+
Suppose the tree is:
194+
```
195+
1
196+
/ \
197+
2 3
198+
/ \
199+
4 5
200+
```
201+
After setting `nodeToParent[root] = NULL`, `nodeToParent` will look like:
202+
```
203+
nodeToParent = { 1: NULL }
204+
```
205+
206+
```cpp
207+
while (!q.empty()) { // While there are nodes to process
208+
Node* front = q.front(); // Get the front node in the queue
209+
q.pop(); // Remove it from the queue
210+
```
211+
212+
2. **Explanation**:
213+
- `front` is the current node we’re processing.
214+
- We remove `front` from the queue as we will now check its children.
215+
216+
```cpp
217+
if (front->data == target) result = front; // Check if this is the target node
218+
```
219+
220+
3. **Explanation**:
221+
- If `front` has the data equal to the target value, we store `front` in `result` as the target node.
222+
223+
```cpp
224+
if (front->left) { // If there is a left child
225+
nodeToParent[front->left] = front; // Map it to its parent
226+
q.push(front->left); // Add left child to queue
227+
}
228+
229+
if (front->right) { // If there is a right child
230+
nodeToParent[front->right] = front; // Map it to its parent
231+
q.push(front->right); // Add right child to queue
232+
}
233+
}
234+
```
235+
236+
4. **Explanation**:
237+
- For each child (left and right) of `front`, we:
238+
- Add it to `nodeToParent` with `front` as the parent.
239+
- Add the child to the queue for processing.
240+
241+
**Example Continued**:
242+
Let’s assume the target node is `2`. The `nodeToParent` map will be built as:
243+
```
244+
nodeToParent = {
245+
1: NULL,
246+
2: 1,
247+
3: 1,
248+
4: 2,
249+
5: 2
250+
}
251+
```
252+
253+
```cpp
254+
return result; // Return the target node
255+
}
256+
```
257+
258+
5. **Explanation**:
259+
- We return the `result`, which contains the target node.
260+
261+
262+
#### Function `burnTree`
263+
264+
```cpp
265+
int burnTree(Node* root, unordered_map<Node*, Node*>& nodeToParent) {
266+
unordered_map<Node*, bool> visited; // Track which nodes have burned
267+
queue<Node*> q; // Queue for level-order burning process
268+
q.push(root); // Start burning from the target node
269+
visited[root] = true; // Mark the target node as visited
270+
int ans = 0; // Time counter for burning process
271+
```
272+
273+
1. **Explanation**:
274+
- `visited` keeps track of nodes that are already burning.
275+
- `q` is initialized with the `root` (target node) to begin the burn.
276+
- `ans` keeps track of the total time needed.
277+
278+
```cpp
279+
while (!q.empty()) {
280+
bool flag = false; // Flag to check if any new nodes catch fire
281+
int size = q.size(); // Current level size in BFS
282+
```
283+
284+
2. **Explanation**:
285+
- `flag` checks if any node catches fire in the current level of the BFS.
286+
- `size` is used to process each level one by one.
287+
288+
```cpp
289+
for (int i = 0; i < size; i++) {
290+
Node* front = q.front(); // Get the front node
291+
q.pop(); // Remove it from the queue
292+
```
293+
294+
3. **Explanation**:
295+
- We process each node at the current level (`size` times).
296+
297+
```cpp
298+
if (front->left && !visited[front->left]) { // Check left child
299+
flag = true; // Mark that a new node caught fire
300+
q.push(front->left); // Add it to queue
301+
visited[front->left] = true; // Mark as visited
302+
}
303+
304+
if (front->right && !visited[front->right]) { // Check right child
305+
flag = true;
306+
q.push(front->right);
307+
visited[front->right] = true;
308+
}
309+
310+
if (nodeToParent[front] && !visited[nodeToParent[front]]) { // Check parent
311+
flag = true;
312+
q.push(nodeToParent[front]);
313+
visited[nodeToParent[front]] = true;
314+
}
315+
```
316+
317+
4. **Explanation**:
318+
- We check each of `front`’s neighbors (left, right, and parent) and spread the fire to unvisited nodes.
319+
- If any new node catches fire, we set `flag = true`.
320+
321+
```cpp
322+
}
323+
324+
if (flag) ans++; // Increase time if any node caught fire in this level
325+
}
326+
327+
return ans; // Return the total time taken to burn the tree
328+
}
329+
```
330+
331+
5. **Explanation**:
332+
- If `flag` is true, increment `ans` because it indicates another minute has passed.
333+
- Return `ans` once all nodes have burned.
334+
335+
**Example Continued**:
336+
With the tree example and target node `2`:
337+
1. **Minute 0**: `q = [2]`
338+
2. **Minute 1**: `q = [1, 4, 5]`
339+
3. **Minute 2**: `q = [3]`
340+
- All nodes have burned, so `ans = 2`.
341+
342+
#### Function `minTime`
343+
344+
```cpp
345+
int minTime(Node* root, int target) {
346+
unordered_map<Node*, Node*> nodeToParent;
347+
Node* targetNode = createParentMapping(root, target, nodeToParent);
348+
349+
return burnTree(targetNode, nodeToParent);
350+
}
351+
```
352+
353+
- This function:
354+
1. Calls `createParentMapping` to get the `targetNode` and `nodeToParent` mapping.
355+
2. Calls `burnTree` to calculate the burn time.
356+
357+
358+
### Output Examples
359+
360+
Example Tree:
361+
```
362+
1
363+
/ \
364+
2 3
365+
/ \
366+
4 5
367+
```
368+
369+
**Input**: Target node is `2`.
370+
**Output**: `2`
371+
**Explanation**:
372+
1. **Time 0**: Start burning at `2`.
373+
2. **Time 1**: Nodes `4`, `5`, and `1` catch fire.
374+
3. **Time 2**: Node `3` catches fire. All nodes have burned.
375+
376+
### Step 5: Time and Space Complexity
377+
378+
- **Time Complexity**:
379+
- `createParentMapping`: \(O(N)\) where \(N\) is the number of nodes, as we perform a single traversal.
380+
- `burnTree`: \(O(N)\), as we again traverse each node once.
381+
- **Overall**: \(O(N)\).
382+
383+
- **Space Complexity**:
384+
- The space complexity is \(O(N)\) for the `nodeToParent` map and `visited` set.
385+
- **Overall**: \(O(N)\).

0 commit comments

Comments
 (0)