|
| 1 | +<h1 align='center'>Bottom - View - of - Binary - Tree</h1> |
| 2 | + |
| 3 | +## Problem Statement |
| 4 | + |
| 5 | +**Problem URL :** [Bottom View of Binary Tree](https://www.geeksforgeeks.org/problems/bottom-view-of-binary-tree/1) |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | +## Problem Explanation |
| 11 | +The **Bottom View** of a binary tree shows the nodes visible when the tree is viewed from the bottom. For each horizontal distance from the root, only the node that appears the lowest in the tree is included in the bottom view. |
| 12 | + |
| 13 | +For example: |
| 14 | + |
| 15 | +Given the binary tree: |
| 16 | +``` |
| 17 | + 1 |
| 18 | + / \ |
| 19 | + 2 3 |
| 20 | + / \ \ |
| 21 | + 4 5 6 |
| 22 | +``` |
| 23 | + |
| 24 | +The **Bottom View** of this binary tree would be `[4, 2, 5, 3, 6]`. |
| 25 | + |
| 26 | +### Step 2: Approach and Explanation |
| 27 | + |
| 28 | +To solve this problem, we can use a level-order traversal (breadth-first traversal) while keeping track of **horizontal distances (HD)** of nodes from the root. |
| 29 | + |
| 30 | +Steps: |
| 31 | +1. **Start at the root** node with an HD of 0. |
| 32 | +2. **For each node**, add its left child with HD decreased by 1 and right child with HD increased by 1. |
| 33 | +3. We use a **map** to keep track of nodes at each HD. In this case, we always update the node at each HD, so the map holds the **last node encountered** at each HD, which will be the bottommost node at that distance. |
| 34 | +4. After traversing all nodes, **extract values** from the map to get nodes from leftmost to rightmost HD. |
| 35 | + |
| 36 | +## Problem Solution |
| 37 | +```cpp |
| 38 | +class Solution { |
| 39 | + public: |
| 40 | + vector <int> bottomView(Node *root) { |
| 41 | + |
| 42 | + vector<int> ans; |
| 43 | + if(root == NULL) return ans; |
| 44 | + |
| 45 | + map<int, int> topNode; |
| 46 | + queue<pair<Node*, int>> q; |
| 47 | + |
| 48 | + q.push({root, 0}); |
| 49 | + |
| 50 | + while(!q.empty()){ |
| 51 | + pair<Node*, int> temp = q.front(); |
| 52 | + q.pop(); |
| 53 | + |
| 54 | + Node* frontNode = temp.first; |
| 55 | + int hd = temp.second; |
| 56 | + |
| 57 | + topNode[hd] = frontNode -> data; |
| 58 | + |
| 59 | + if(frontNode -> left){ |
| 60 | + q.push({frontNode -> left, hd -1}); |
| 61 | + } |
| 62 | + |
| 63 | + if(frontNode -> right){ |
| 64 | + q.push({frontNode -> right, hd + 1}); |
| 65 | + } |
| 66 | + |
| 67 | + } |
| 68 | + for(auto i : topNode){ |
| 69 | + ans.push_back(i.second); |
| 70 | + } |
| 71 | + |
| 72 | + |
| 73 | + return ans; |
| 74 | + } |
| 75 | +}; |
| 76 | +``` |
| 77 | +
|
| 78 | +## Problem Solution Explanation |
| 79 | +
|
| 80 | +```cpp |
| 81 | +class Solution { |
| 82 | + public: |
| 83 | + vector <int> bottomView(Node *root) { |
| 84 | +``` |
| 85 | +- Defines a class `Solution` with a public function `bottomView` that takes the root of the binary tree as input and returns a vector containing the bottom view nodes. |
| 86 | + |
| 87 | +```cpp |
| 88 | + vector<int> ans; |
| 89 | + if(root == NULL) return ans; |
| 90 | +``` |
| 91 | +- Initializes an empty vector `ans` to store the bottom view nodes. |
| 92 | +- If the root is `NULL`, the tree is empty, so we return `ans` as an empty vector. |
| 93 | + |
| 94 | +```cpp |
| 95 | + map<int, int> topNode; |
| 96 | + queue<pair<Node*, int>> q; |
| 97 | +``` |
| 98 | +- `topNode`: A map where the key is the HD, and the value is the data of the bottommost node at that HD. As we process each node, we overwrite previous values at the same HD, ensuring the map holds the lowest (last) node encountered at each HD. |
| 99 | +- `q`: A queue to perform level-order traversal, storing pairs of nodes and their HD. |
| 100 | + |
| 101 | +```cpp |
| 102 | + q.push({root, 0}); |
| 103 | +``` |
| 104 | +- Adds the root node to the queue with an HD of `0`. |
| 105 | +
|
| 106 | +```cpp |
| 107 | + while(!q.empty()){ |
| 108 | + pair<Node*, int> temp = q.front(); |
| 109 | + q.pop(); |
| 110 | + |
| 111 | + Node* frontNode = temp.first; |
| 112 | + int hd = temp.second; |
| 113 | +``` |
| 114 | +- The `while` loop processes all nodes in the queue. |
| 115 | +- Retrieves the front element in the queue, `temp`, which is a pair containing a node (`frontNode`) and its HD (`hd`). |
| 116 | +- Removes this element from the queue with `q.pop()`. |
| 117 | + |
| 118 | +```cpp |
| 119 | + topNode[hd] = frontNode -> data; |
| 120 | +``` |
| 121 | +- For each node, update the map `topNode` at the HD `hd` with the node’s data. This will keep overwriting any previous node at that HD, ensuring that only the bottommost node remains. |
| 122 | + |
| 123 | +```cpp |
| 124 | + if(frontNode -> left){ |
| 125 | + q.push({frontNode -> left, hd -1}); |
| 126 | + } |
| 127 | +``` |
| 128 | +- If the current node has a left child, add it to the queue with an HD of `hd - 1` (one unit to the left). |
| 129 | +
|
| 130 | +```cpp |
| 131 | + if(frontNode -> right){ |
| 132 | + q.push({frontNode -> right, hd + 1}); |
| 133 | + } |
| 134 | +``` |
| 135 | +- If the current node has a right child, add it to the queue with an HD of `hd + 1` (one unit to the right). |
| 136 | + |
| 137 | +```cpp |
| 138 | + } |
| 139 | +``` |
| 140 | +- Ends the `while` loop once all nodes have been processed. |
| 141 | + |
| 142 | +```cpp |
| 143 | + for(auto i : topNode){ |
| 144 | + ans.push_back(i.second); |
| 145 | + } |
| 146 | +``` |
| 147 | +- Loops through the `topNode` map in ascending order of HD, pushing each node’s data into the `ans` vector. This ensures the nodes are ordered from the leftmost to rightmost in the bottom view. |
| 148 | +
|
| 149 | +```cpp |
| 150 | + return ans; |
| 151 | + } |
| 152 | +}; |
| 153 | +``` |
| 154 | +- Returns the `ans` vector containing the bottom view of the binary tree. |
| 155 | + |
| 156 | +--- |
| 157 | + |
| 158 | +### Step 4: Output Examples with Explanation |
| 159 | + |
| 160 | +Consider this binary tree: |
| 161 | + |
| 162 | +``` |
| 163 | + 1 |
| 164 | + / \ |
| 165 | + 2 3 |
| 166 | + / \ \ |
| 167 | + 4 5 6 |
| 168 | +``` |
| 169 | + |
| 170 | +**Horizontal Distances (HDs)**: |
| 171 | +- HD `-2`: Node `4` |
| 172 | +- HD `-1`: Node `2` |
| 173 | +- HD `0`: Node `5` (bottommost at this HD) |
| 174 | +- HD `1`: Node `3` |
| 175 | +- HD `2`: Node `6` |
| 176 | + |
| 177 | +The bottom view will be `[4, 2, 5, 3, 6]`. |
| 178 | + |
| 179 | +Another example: |
| 180 | + |
| 181 | +``` |
| 182 | + 1 |
| 183 | + / \ |
| 184 | + 2 3 |
| 185 | + \ |
| 186 | + 4 |
| 187 | + \ |
| 188 | + 5 |
| 189 | + \ |
| 190 | + 6 |
| 191 | +``` |
| 192 | + |
| 193 | +**Bottom view** for this tree would be `[2, 4, 5, 6]`. |
| 194 | + |
| 195 | +--- |
| 196 | + |
| 197 | +### Step 5: Time and Space Complexity |
| 198 | + |
| 199 | +#### Time Complexity |
| 200 | +- **O(N)**: We visit each node once in the level-order traversal, so the time complexity is proportional to the number of nodes, **N**. |
| 201 | + |
| 202 | +#### Space Complexity |
| 203 | +- **O(N)**: The space required by the map `topNode` is proportional to the number of unique HDs, which is at most **N**. |
| 204 | +- The queue `q` also holds at most **N** nodes in the worst case. |
| 205 | + |
| 206 | +Thus, the overall space complexity is **O(N)**. |
| 207 | + |
| 208 | +This solution efficiently finds the bottom view by performing a level-order traversal and using HDs to keep only the bottommost node at each HD. |
0 commit comments