|
| 1 | +<h1 align='center'>Amount - of Time - For Binary - To be - Infected</h1> |
| 2 | + |
| 3 | +## Problem Statement |
| 4 | + |
| 5 | +**Problem URL :** [Amount of Time for Binary To be Infected](https://leetcode.com/problems/amount-of-time-for-binary-tree-to-be-infected/) |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | +## Problem Explanation |
| 11 | +The problem is titled **"Amount of Time for Binary Tree to be Infected"** on LeetCode. Given a binary tree where each node has a unique integer value, we select a `start` node, which becomes infected at time 0. The infection spreads to all directly connected nodes (left child, right child, and parent node) each minute. We need to determine the total time required for the entire tree to be infected. |
| 12 | + |
| 13 | +### Constraints |
| 14 | +- Nodes are only infected if connected to an already infected node. |
| 15 | +- You are given the `start` node's value, which initiates the infection. |
| 16 | + |
| 17 | +### Example |
| 18 | +Imagine the binary tree: |
| 19 | +``` |
| 20 | + 1 |
| 21 | + / \ |
| 22 | + 2 3 |
| 23 | + / \ |
| 24 | + 4 5 |
| 25 | +``` |
| 26 | +If we start at node `2`, the infection spreads like this: |
| 27 | +1. **Minute 0**: Node 2 is infected. |
| 28 | +2. **Minute 1**: Nodes 1 and 4 (connected to node 2) are infected. |
| 29 | +3. **Minute 2**: Nodes 3 and 5 become infected. |
| 30 | + |
| 31 | +The entire tree is infected in **2 minutes**. |
| 32 | + |
| 33 | +### Edge Cases |
| 34 | +- If the tree has only one node, it’s already infected at minute 0. |
| 35 | +- If the `start` node is a leaf node, the infection needs more time to spread upward to the root and then to other branches. |
| 36 | + |
| 37 | +## Step 2: Approach |
| 38 | + |
| 39 | +### High-Level Overview |
| 40 | +1. First, find the `start` node in the binary tree. |
| 41 | +2. Track each node’s parent using a map for easy access to all adjacent nodes. |
| 42 | +3. Perform a level-order traversal (BFS) from the `start` node to spread the infection. Keep track of infected nodes to avoid re-infecting nodes. |
| 43 | + |
| 44 | +### Step-by-Step Breakdown |
| 45 | +1. **Identify the Start Node**: Traverse the tree to find the `start` node and build a map that links each node to its parent. |
| 46 | +2. **Infection Spread Simulation**: Using a BFS from the `start` node, simulate the infection spread minute-by-minute by visiting all uninfected neighboring nodes. |
| 47 | +3. **Count the Time**: For each level in BFS, increment the time until no uninfected nodes remain. |
| 48 | + |
| 49 | +### Pseudocode |
| 50 | +1. Traverse the tree to find the start node and populate the parent map. |
| 51 | +2. Initiate BFS from the start node, marking each visited node as infected. |
| 52 | +3. For each level, count the minutes until all nodes are infected. |
| 53 | + |
| 54 | +## Problem Solution |
| 55 | +```cpp |
| 56 | +/** |
| 57 | + * Definition for a binary tree node. |
| 58 | + * struct TreeNode { |
| 59 | + * int val; |
| 60 | + * TreeNode *left; |
| 61 | + * TreeNode *right; |
| 62 | + * TreeNode() : val(0), left(nullptr), right(nullptr) {} |
| 63 | + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} |
| 64 | + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} |
| 65 | + * }; |
| 66 | + */ |
| 67 | +class Solution { |
| 68 | +public: |
| 69 | + TreeNode* startPoint(TreeNode* root, int start, unordered_map<TreeNode*, TreeNode*> &childParentMapping){ |
| 70 | + TreeNode* result = NULL; |
| 71 | + queue<TreeNode*> q; |
| 72 | + q.push(root); |
| 73 | + |
| 74 | + childParentMapping[root] = NULL; |
| 75 | + |
| 76 | + while(!q.empty()){ |
| 77 | + TreeNode* front = q.front(); |
| 78 | + q.pop(); |
| 79 | + |
| 80 | + if(front -> val == start){ |
| 81 | + result = front; |
| 82 | + } |
| 83 | + |
| 84 | + if(front -> left){ |
| 85 | + childParentMapping[front -> left] = front; |
| 86 | + q.push(front -> left); |
| 87 | + } |
| 88 | + |
| 89 | + if(front -> right){ |
| 90 | + childParentMapping[front -> right] = front; |
| 91 | + q.push(front -> right); |
| 92 | + } |
| 93 | + } |
| 94 | + |
| 95 | + return result; |
| 96 | + } |
| 97 | + |
| 98 | + int t_infected_time(TreeNode* root, unordered_map<TreeNode*, TreeNode*> childParentMapping){ |
| 99 | + int minutes = -1; |
| 100 | + |
| 101 | + unordered_map<TreeNode*, bool> infected; |
| 102 | + queue<TreeNode*> q; |
| 103 | + |
| 104 | + q.push(root); |
| 105 | + |
| 106 | + infected[root] = true; |
| 107 | + |
| 108 | + while(!q.empty()){ |
| 109 | + int size = q.size(); |
| 110 | + bool flag = true; |
| 111 | + |
| 112 | + for(int i = 0; i < size; i++){ |
| 113 | + |
| 114 | + TreeNode* front = q.front(); |
| 115 | + q.pop(); |
| 116 | + |
| 117 | + if(front -> left && !infected[front -> left]){ |
| 118 | + flag = true; |
| 119 | + q.push(front -> left); |
| 120 | + infected[front -> left] = true; |
| 121 | + } |
| 122 | + |
| 123 | + if(front -> right && !infected[front -> right]){ |
| 124 | + flag = true; |
| 125 | + q.push(front -> right); |
| 126 | + infected[front -> right] = true; |
| 127 | + } |
| 128 | + |
| 129 | + if(childParentMapping[front] && !infected[childParentMapping[front]]){ |
| 130 | + flag = true; |
| 131 | + q.push(childParentMapping[front]); |
| 132 | + infected[childParentMapping[front]] = true; |
| 133 | + } |
| 134 | + } |
| 135 | + |
| 136 | + if(flag == true) minutes++; |
| 137 | + } |
| 138 | + |
| 139 | + return minutes; |
| 140 | + } |
| 141 | + int amountOfTime(TreeNode* root, int start) { |
| 142 | + unordered_map<TreeNode*, TreeNode*> childParentMapping; |
| 143 | + TreeNode* startNode = startPoint(root, start, childParentMapping); |
| 144 | + return t_infected_time(startNode, childParentMapping); |
| 145 | + } |
| 146 | +}; |
| 147 | +``` |
| 148 | + |
| 149 | +## Problem Solution Explanation |
| 150 | + |
| 151 | +```cpp |
| 152 | +/** |
| 153 | + * Definition for a binary tree node. |
| 154 | + * struct TreeNode { |
| 155 | + * int val; |
| 156 | + * TreeNode *left; |
| 157 | + * TreeNode *right; |
| 158 | + * TreeNode() : val(0), left(nullptr), right(nullptr) {} |
| 159 | + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} |
| 160 | + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} |
| 161 | + * }; |
| 162 | + */ |
| 163 | +class Solution { |
| 164 | +``` |
| 165 | +
|
| 166 | +This part sets up the `TreeNode` structure, representing each node in the binary tree, with `val` holding the node's value, and `left` and `right` pointers representing child nodes. It defines three constructors: |
| 167 | +1. **Default Constructor**: Creates a node with `val = 0`. |
| 168 | +2. **Parameterized Constructor**: Creates a node with a given `val`. |
| 169 | +3. **Complete Constructor**: Creates a node with a given `val`, `left`, and `right`. |
| 170 | +
|
| 171 | +
|
| 172 | +### Function 1: `startPoint` |
| 173 | +
|
| 174 | +This function finds the `start` node in the tree and builds a map linking each child node to its parent for easy traversal. |
| 175 | +
|
| 176 | +```cpp |
| 177 | +TreeNode* startPoint(TreeNode* root, int start, unordered_map<TreeNode*, TreeNode*> &childParentMapping) { |
| 178 | + TreeNode* result = NULL; // Holds the start node reference |
| 179 | + queue<TreeNode*> q; // Queue for level-order traversal |
| 180 | + q.push(root); |
| 181 | +
|
| 182 | + childParentMapping[root] = NULL; // Root has no parent |
| 183 | +
|
| 184 | + while (!q.empty()) { |
| 185 | + TreeNode* front = q.front(); |
| 186 | + q.pop(); |
| 187 | +
|
| 188 | + if (front->val == start) { // Check if we found the start node |
| 189 | + result = front; |
| 190 | + } |
| 191 | +
|
| 192 | + if (front->left) { // Map left child to its parent |
| 193 | + childParentMapping[front->left] = front; |
| 194 | + q.push(front->left); |
| 195 | + } |
| 196 | +
|
| 197 | + if (front->right) { // Map right child to its parent |
| 198 | + childParentMapping[front->right] = front; |
| 199 | + q.push(front->right); |
| 200 | + } |
| 201 | + } |
| 202 | +
|
| 203 | + return result; // Return the start node |
| 204 | +} |
| 205 | +``` |
| 206 | + |
| 207 | +#### Example 1: Basic Tree |
| 208 | + |
| 209 | +Consider this tree and suppose `start = 2`: |
| 210 | + |
| 211 | +``` |
| 212 | + 1 |
| 213 | + / \ |
| 214 | + 2 3 |
| 215 | + / \ |
| 216 | + 4 5 |
| 217 | +``` |
| 218 | + |
| 219 | +1. **Queue Initialization**: `q = [1]` |
| 220 | +2. **Map Creation**: `childParentMapping = {1: NULL}` |
| 221 | +3. **Node 1 Processing**: |
| 222 | + - Set `2`’s parent to `1`: `childParentMapping = {1: NULL, 2: 1}` |
| 223 | + - Set `3`’s parent to `1`: `childParentMapping = {1: NULL, 2: 1, 3: 1}` |
| 224 | + - `q = [2, 3]` |
| 225 | +4. **Node 2 Processing**: |
| 226 | + - `start` node found, so `result = 2` |
| 227 | + - Set `4`’s parent to `2`: `childParentMapping = {1: NULL, 2: 1, 3: 1, 4: 2}` |
| 228 | + - Set `5`’s parent to `2`: `childParentMapping = {1: NULL, 2: 1, 3: 1, 4: 2, 5: 2}` |
| 229 | + - `q = [3, 4, 5]` |
| 230 | +5. **Final Output**: `result = 2` |
| 231 | + |
| 232 | +This completes the map of each node to its parent and identifies `2` as the starting node. |
| 233 | + |
| 234 | + |
| 235 | +### Function 2: `t_infected_time` |
| 236 | + |
| 237 | +This function calculates the total time required to infect the entire tree, starting from the given node. It uses a breadth-first search (BFS) to spread the infection level by level. |
| 238 | + |
| 239 | +```cpp |
| 240 | +int t_infected_time(TreeNode* root, unordered_map<TreeNode*, TreeNode*> childParentMapping) { |
| 241 | + int minutes = -1; // Infection time counter |
| 242 | + unordered_map<TreeNode*, bool> infected; // Track infected nodes |
| 243 | + queue<TreeNode*> q; |
| 244 | + |
| 245 | + q.push(root); // Start from the root node |
| 246 | + infected[root] = true; |
| 247 | + |
| 248 | + while (!q.empty()) { |
| 249 | + int size = q.size(); // Number of nodes in the current level |
| 250 | + bool flag = false; // Track if new nodes are infected this minute |
| 251 | + |
| 252 | + for (int i = 0; i < size; i++) { |
| 253 | + TreeNode* front = q.front(); |
| 254 | + q.pop(); |
| 255 | + |
| 256 | + // Check left child |
| 257 | + if (front->left && !infected[front->left]) { |
| 258 | + flag = true; |
| 259 | + q.push(front->left); |
| 260 | + infected[front->left] = true; |
| 261 | + } |
| 262 | + |
| 263 | + // Check right child |
| 264 | + if (front->right && !infected[front->right]) { |
| 265 | + flag = true; |
| 266 | + q.push(front->right); |
| 267 | + infected[front->right] = true; |
| 268 | + } |
| 269 | + |
| 270 | + // Check parent |
| 271 | + if (childParentMapping[front] && !infected[childParentMapping[front]]) { |
| 272 | + flag = true; |
| 273 | + q.push(childParentMapping[front]); |
| 274 | + infected[childParentMapping[front]] = true; |
| 275 | + } |
| 276 | + } |
| 277 | + |
| 278 | + if (flag) minutes++; // Increment if any new infections occurred |
| 279 | + } |
| 280 | + |
| 281 | + return minutes; |
| 282 | +} |
| 283 | +``` |
| 284 | +
|
| 285 | +#### Example 2: Infection Spread |
| 286 | +
|
| 287 | +Using the previous tree with `start = 2`, let’s see how the infection spreads: |
| 288 | +
|
| 289 | +1. **Minute 0**: Node `2` is infected (`q = [2]`) |
| 290 | +2. **Minute 1**: |
| 291 | + - Infect nodes `1` and `4`: `q = [1, 4]` |
| 292 | +3. **Minute 2**: |
| 293 | + - Infect nodes `3` and `5`: `q = [3, 5]` |
| 294 | +4. **Result**: The tree is fully infected in **2 minutes**. |
| 295 | +
|
| 296 | +### Final Function: `amountOfTime` |
| 297 | +
|
| 298 | +This function ties everything together by calling `startPoint` to find the start node and `t_infected_time` to calculate the time to infect the tree. |
| 299 | +
|
| 300 | +```cpp |
| 301 | +int amountOfTime(TreeNode* root, int start) { |
| 302 | + unordered_map<TreeNode*, TreeNode*> childParentMapping; |
| 303 | + TreeNode* startNode = startPoint(root, start, childParentMapping); |
| 304 | + return t_infected_time(startNode, childParentMapping); |
| 305 | +} |
| 306 | +``` |
| 307 | + |
| 308 | +1. **Example**: For the tree above, `amountOfTime(root, 2)` returns `2` minutes. |
| 309 | + |
| 310 | +### Step 4: Additional Examples |
| 311 | + |
| 312 | +1. **Single Node Tree**: Tree with one node (start = 1). |
| 313 | + - **Input**: `root = [1]`, `start = 1` |
| 314 | + - **Output**: `0` minutes (tree is infected immediately). |
| 315 | + |
| 316 | +2. **Skewed Tree** (like a linked list): |
| 317 | + ``` |
| 318 | + 1 |
| 319 | + \ |
| 320 | + 2 |
| 321 | + \ |
| 322 | + 3 |
| 323 | + \ |
| 324 | + 4 |
| 325 | + ``` |
| 326 | + - **Input**: `root = [1, null, 2, null, 3, null, 4]`, `start = 1` |
| 327 | + - **Output**: `3` minutes (infection moves one node per minute down the chain). |
| 328 | + |
| 329 | + |
| 330 | +### Step 5: Time and Space Complexity Analysis |
| 331 | + |
| 332 | +- **Time Complexity**: \(O(n)\), where \(n\) is the number of nodes in the tree. Each node is visited once during `startPoint` and `t_infected_time`. |
| 333 | +- **Space Complexity**: \(O(n)\) for the parent map, infected map, and queue. |
0 commit comments