|
| 1 | +<h1 align='center'>Flatten - Binary - Tree - to - Linked - List</h1> |
| 2 | + |
| 3 | +## Problem Statement |
| 4 | + |
| 5 | +**Problem URL :** [Flatten Binary Tree to Linked List](https://leetcode.com/problems/flatten-binary-tree-to-linked-list/) |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | +## Problem Explanation |
| 11 | + |
| 12 | +**Problem**: Given the root of a binary tree, the task is to flatten the tree into a linked list **in-place**. The flattened tree should follow the structure of a pre-order traversal, where each node's left child is null and the right child points to the next node in the traversal order. |
| 13 | + |
| 14 | +**Constraints**: |
| 15 | +1. Do not use extra space for a new data structure. |
| 16 | +2. Transform the tree in-place without affecting the original node values. |
| 17 | + |
| 18 | +**Example**: |
| 19 | +Suppose we have the following binary tree: |
| 20 | + |
| 21 | +``` |
| 22 | + 1 |
| 23 | + / \ |
| 24 | + 2 5 |
| 25 | + / \ \ |
| 26 | +3 4 6 |
| 27 | +``` |
| 28 | + |
| 29 | +The flattened linked list representation should look like this: |
| 30 | + |
| 31 | +``` |
| 32 | +1 -> 2 -> 3 -> 4 -> 5 -> 6 |
| 33 | +``` |
| 34 | + |
| 35 | +### Real-world Analogy |
| 36 | +Imagine we have a series of rooms (nodes), where each room has one door (node connection) that leads to another room. Our task is to rearrange the rooms in such a way that there's only one straight hallway (linked list) connecting them all, while preserving their order as they would appear in a depth-first search of the original layout. |
| 37 | + |
| 38 | +**Edge Cases**: |
| 39 | +- An empty tree (`root = null`). |
| 40 | +- A tree with only one node. |
| 41 | +- A tree where every node has only a left child or only a right child. |
| 42 | + |
| 43 | +--- |
| 44 | + |
| 45 | +### Step 2: Approach |
| 46 | + |
| 47 | +#### High-Level Overview |
| 48 | +To solve this problem, we use the **Morris Traversal** technique to modify the tree in-place. The basic idea is to find the rightmost node of the left subtree (the in-order predecessor) for each node and link it to the current node's right subtree. Then, we shift the left subtree to the right and continue to the next node. |
| 49 | + |
| 50 | +#### Step-by-Step Breakdown |
| 51 | + |
| 52 | +1. **Start at the Root Node**: Initialize a pointer `current` to traverse the tree starting from `root`. |
| 53 | +2. **Process Each Node**: |
| 54 | + - If `current` has a left child, find its in-order predecessor in the left subtree: |
| 55 | + - Traverse to the rightmost node in `current`'s left subtree. |
| 56 | + - **Link the Right Subtree**: Link this rightmost node's right pointer to `current`'s right subtree. |
| 57 | + - **Move the Left Subtree**: Move the left subtree to the right and set `current`'s left pointer to null. |
| 58 | +3. **Continue to the Right Subtree**: Move `current` to `current->right` and repeat until all nodes are visited. |
| 59 | + |
| 60 | +#### Visual Aid |
| 61 | +Here’s how the transformation works for each step in the above example: |
| 62 | + |
| 63 | +``` |
| 64 | +Original Tree: |
| 65 | + 1 |
| 66 | + / \ |
| 67 | + 2 5 |
| 68 | + / \ \ |
| 69 | +3 4 6 |
| 70 | +
|
| 71 | +Step-by-Step Transformation: |
| 72 | +1. Link 4's right to 5 (right subtree of 1), move 2 to the right of 1. |
| 73 | +2. Link 3's right to 4 (right subtree of 2), move 3 to the right of 2. |
| 74 | +
|
| 75 | +Final Flattened Tree: |
| 76 | +1 -> 2 -> 3 -> 4 -> 5 -> 6 |
| 77 | +``` |
| 78 | + |
| 79 | +## Problem Solution |
| 80 | +```cpp |
| 81 | +/** |
| 82 | + * Definition for a binary tree node. |
| 83 | + * struct TreeNode { |
| 84 | + * int val; |
| 85 | + * TreeNode *left; |
| 86 | + * TreeNode *right; |
| 87 | + * TreeNode() : val(0), left(nullptr), right(nullptr) {} |
| 88 | + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} |
| 89 | + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} |
| 90 | + * }; |
| 91 | + */ |
| 92 | +class Solution { |
| 93 | +public: |
| 94 | + void flatten(TreeNode* root) { |
| 95 | + TreeNode* current = root; |
| 96 | + |
| 97 | + while(current != NULL){ |
| 98 | + if(current -> left){ |
| 99 | + TreeNode* pred = current -> left; |
| 100 | + |
| 101 | + while(pred -> right){ |
| 102 | + pred = pred -> right; |
| 103 | + } |
| 104 | + pred -> right = current -> right; |
| 105 | + current -> right = current -> left; |
| 106 | + } |
| 107 | + |
| 108 | + current -> left = NULL; |
| 109 | + current = current -> right; |
| 110 | + } |
| 111 | + } |
| 112 | +}; |
| 113 | +``` |
| 114 | + |
| 115 | +## Problem Solution Explanation |
| 116 | +Let's go through the source code for the "Flatten Binary Tree to Linked List" problem in detail, line by line, to understand how each part contributes to the solution. |
| 117 | + |
| 118 | +```cpp |
| 119 | +#include <iostream> |
| 120 | +using namespace std; |
| 121 | + |
| 122 | +struct TreeNode { |
| 123 | + int val; |
| 124 | + TreeNode *left; |
| 125 | + TreeNode *right; |
| 126 | + TreeNode() : val(0), left(nullptr), right(nullptr) {} |
| 127 | + TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} |
| 128 | + TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} |
| 129 | +}; |
| 130 | +``` |
| 131 | +
|
| 132 | +- **TreeNode Structure**: This defines a binary tree node. Each `TreeNode` has: |
| 133 | + - An integer `val` representing the value of the node. |
| 134 | + - Two pointers, `left` and `right`, pointing to the left and right children of the node. |
| 135 | + - Three constructors: |
| 136 | + - `TreeNode()` initializes a node with a default value `0` and both children as `nullptr`. |
| 137 | + - `TreeNode(int x)` initializes a node with value `x`, left child as `nullptr`, and right child as `nullptr`. |
| 138 | + - `TreeNode(int x, TreeNode *left, TreeNode *right)` initializes a node with value `x`, a left child as `left`, and a right child as `right`. |
| 139 | +
|
| 140 | +--- |
| 141 | +
|
| 142 | +```cpp |
| 143 | +class Solution { |
| 144 | +public: |
| 145 | + void flatten(TreeNode* root) { |
| 146 | + TreeNode* current = root; |
| 147 | +``` |
| 148 | + |
| 149 | +- **Solution Class**: The `Solution` class contains the `flatten` method, which is the function that will modify the binary tree to flatten it into a linked list. |
| 150 | +- **void flatten(TreeNode* root)**: This function takes a pointer to the root of a binary tree as input. |
| 151 | +- `TreeNode* current = root;`: Initializes a pointer, `current`, to traverse the tree, starting at the root node. |
| 152 | + |
| 153 | +--- |
| 154 | + |
| 155 | +```cpp |
| 156 | + while(current != nullptr) { |
| 157 | +``` |
| 158 | +
|
| 159 | +- **while(current != nullptr)**: This loop iterates over each node in the tree, moving along the flattened "linked list." The loop continues until `current` becomes `nullptr`, meaning all nodes have been processed. |
| 160 | +
|
| 161 | +--- |
| 162 | +
|
| 163 | +```cpp |
| 164 | + if(current->left) { |
| 165 | + TreeNode* pred = current->left; |
| 166 | +``` |
| 167 | + |
| 168 | +- **if(current->left)**: This checks if the current node has a left child. If it does, we need to re-arrange the left and right subtrees of `current` to continue the flattening process. |
| 169 | +- **TreeNode* pred = current->left;**: `pred` is set to the left child of `current`. This pointer will be used to find the rightmost node in the left subtree of `current`, which will help in linking the left subtree correctly. |
| 170 | + |
| 171 | +--- |
| 172 | + |
| 173 | +```cpp |
| 174 | + while(pred->right) { |
| 175 | + pred = pred->right; |
| 176 | + } |
| 177 | +``` |
| 178 | +
|
| 179 | +- **while(pred->right)**: This inner loop traverses the right subtree of `pred` to find the rightmost node in `current`'s left subtree. |
| 180 | + - The reason we need the rightmost node is to link it to `current`'s right subtree later on, ensuring that all nodes are still accessible in the correct order. |
| 181 | +- `pred = pred->right;`: This line moves `pred` one step to the right, iteratively finding the rightmost node in the left subtree of `current`. |
| 182 | +
|
| 183 | +--- |
| 184 | +
|
| 185 | +```cpp |
| 186 | + pred->right = current->right; |
| 187 | +``` |
| 188 | + |
| 189 | +- **pred->right = current->right;**: Once the rightmost node (`pred`) in the left subtree of `current` is found, its `right` pointer is linked to the right subtree of `current`. |
| 190 | + - This ensures that the original right subtree of `current` is preserved and attached to the end of `current`'s left subtree. |
| 191 | + |
| 192 | +--- |
| 193 | + |
| 194 | +```cpp |
| 195 | + current->right = current->left; |
| 196 | + current->left = nullptr; |
| 197 | +``` |
| 198 | + |
| 199 | +- **current->right = current->left;**: The left subtree of `current` is now assigned to the `right` of `current`, effectively moving it to the right side. |
| 200 | + - This is a crucial step as we want all left children to be removed in the final linked list, and the left subtree to be placed in the right position. |
| 201 | +- **current->left = nullptr;**: This sets `current`'s left child to `nullptr`, flattening the current node's structure as per the requirement that each node should have only a right child in the flattened list. |
| 202 | + |
| 203 | +--- |
| 204 | + |
| 205 | +```cpp |
| 206 | + } |
| 207 | + current = current->right; |
| 208 | + } |
| 209 | + } |
| 210 | +}; |
| 211 | +``` |
| 212 | + |
| 213 | +- **current = current->right;**: Moves `current` to its right child. Since we’ve moved the entire left subtree to the right, this line ensures that `current` progresses along the "linked list" that’s being created. |
| 214 | +- **End of While Loop**: The `while` loop ends when `current` becomes `nullptr`, indicating that all nodes have been processed and the tree is fully flattened. |
| 215 | + |
| 216 | +--- |
| 217 | + |
| 218 | +### Summary of the Code's Functioning |
| 219 | + |
| 220 | +1. For each node with a left child, we find the rightmost node of that left subtree. |
| 221 | +2. We link this rightmost node's `right` pointer to the current node’s right subtree. |
| 222 | +3. We move the left subtree to the right and set the left pointer to `nullptr`. |
| 223 | +4. Finally, we advance to the next node in the newly structured list. |
| 224 | + |
| 225 | +### Example Walkthrough |
| 226 | + |
| 227 | +Consider this binary tree: |
| 228 | + |
| 229 | +``` |
| 230 | + 1 |
| 231 | + / \ |
| 232 | + 2 5 |
| 233 | + / \ \ |
| 234 | +3 4 6 |
| 235 | +``` |
| 236 | + |
| 237 | +Step-by-step flattening process: |
| 238 | + |
| 239 | +1. **Node 1**: Has a left child, `2`. Traverse the right subtree of `2` to find `4`. Set `4`'s right to `1`'s right subtree (`5`). Move `2` to the right of `1`, setting `1`'s left to `nullptr`. |
| 240 | + - Intermediate state: |
| 241 | + ``` |
| 242 | + 1 |
| 243 | + \ |
| 244 | + 2 |
| 245 | + / \ |
| 246 | + 3 4 |
| 247 | + \ |
| 248 | + 5 |
| 249 | + \ |
| 250 | + 6 |
| 251 | + ``` |
| 252 | + |
| 253 | +2. **Node 2**: Has a left child, `3`. Since `3` has no right child, set `3`'s right to `2`'s right subtree (`4`). Move `3` to the right of `2`, setting `2`'s left to `nullptr`. |
| 254 | + - Intermediate state: |
| 255 | + ``` |
| 256 | + 1 |
| 257 | + \ |
| 258 | + 2 |
| 259 | + \ |
| 260 | + 3 |
| 261 | + \ |
| 262 | + 4 |
| 263 | + \ |
| 264 | + 5 |
| 265 | + \ |
| 266 | + 6 |
| 267 | + ``` |
| 268 | + |
| 269 | +3. **Node 3, 4, 5**: Each of these nodes has no left child, so we simply move to the right each time. |
| 270 | + |
| 271 | +4. **Final Flattened List**: |
| 272 | + ``` |
| 273 | + 1 -> 2 -> 3 -> 4 -> 5 -> 6 |
| 274 | + ``` |
| 275 | + |
| 276 | +--- |
| 277 | + |
| 278 | +### Step 5: Time and Space Complexity |
| 279 | + |
| 280 | +- **Time Complexity**: \( O(n) \), where \( n \) is the number of nodes in the tree. Each node is visited a fixed number of times. |
| 281 | + |
| 282 | +- **Space Complexity**: \( O(1) \), since we’re transforming the tree in-place without using extra space for recursion or auxiliary data structures. |
0 commit comments