|
| 1 | +<h1 align='center'>Diameter - Of a - Binary - Tree</h1> |
| 2 | + |
| 3 | +## Problem Statement |
| 4 | + |
| 5 | +**Problem URL :** [Diameter of A Binary Tree](https://www.geeksforgeeks.org/problems/diameter-of-binary-tree/1) |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | +## Problem Explanation |
| 11 | + |
| 12 | +In this problem, you need to find the **diameter** of a binary tree. The diameter of a binary tree is the length of the longest path between any two nodes in the tree. The path may or may not pass through the root node, and the diameter is calculated based on the **number of nodes** in this longest path, including both endpoints. |
| 13 | + |
| 14 | +#### Examples: |
| 15 | +1. **Example 1**: |
| 16 | + ``` |
| 17 | + 1 |
| 18 | + / \ |
| 19 | + 2 3 |
| 20 | + / \ |
| 21 | + 4 5 |
| 22 | + ``` |
| 23 | + - The longest path is from node `4` to node `5` through node `2`, with a total of `4` nodes in the path (`4 → 2 → 1 → 3`). |
| 24 | + - The diameter here is `4`. |
| 25 | + |
| 26 | +2. **Example 2**: |
| 27 | + ``` |
| 28 | + 1 |
| 29 | + / |
| 30 | + 2 |
| 31 | + / |
| 32 | + 3 |
| 33 | + ``` |
| 34 | + - The longest path is from node `3` to node `1`, which contains three nodes. |
| 35 | + - The diameter here is `3`. |
| 36 | + |
| 37 | +3. **Example 3**: |
| 38 | + - For an empty tree (`root == NULL`), the diameter is `0`. |
| 39 | + |
| 40 | +### Step 2: Approach to Solve the Problem |
| 41 | + |
| 42 | +#### Beginner-Friendly Thinking Process: |
| 43 | + |
| 44 | +1. **Recursive Traversal to Calculate Path Lengths**: |
| 45 | + - This problem requires calculating both **diameters** and **heights** of subtrees for every node. |
| 46 | + - At each node, three potential path lengths (or diameters) can be considered: |
| 47 | + - The diameter of the left subtree. |
| 48 | + - The diameter of the right subtree. |
| 49 | + - The path that passes through the current node, calculated as the sum of the heights of the left and right subtrees plus one (for the current node itself). |
| 50 | + |
| 51 | +2. **Combine Results**: |
| 52 | + - For each node, take the maximum of these three options and store this maximum as the diameter. |
| 53 | + - The height of the current subtree can be calculated as `1 + max(left height, right height)`. |
| 54 | + |
| 55 | +3. **Return Results**: |
| 56 | + - Use a helper function `diameterFast` that returns a `pair<int, int>`, where: |
| 57 | + - `first` is the diameter for that subtree. |
| 58 | + - `second` is the height of that subtree. |
| 59 | + |
| 60 | + |
| 61 | +## Problem Solution |
| 62 | +```cpp |
| 63 | +class Solution { |
| 64 | + public: |
| 65 | + pair<int, int> diameterFast(Node* root){ |
| 66 | + // base case |
| 67 | + if(root == NULL){ |
| 68 | + pair<int, int> p = make_pair(0, 0); |
| 69 | + return p; |
| 70 | + }; |
| 71 | + |
| 72 | + pair<int, int> left = diameterFast(root -> left); |
| 73 | + pair<int, int> right = diameterFast(root -> right); |
| 74 | + |
| 75 | + int op1 = left.first; |
| 76 | + int op2 = right.first; |
| 77 | + int op3 = left.second + right.second + 1; |
| 78 | + |
| 79 | + |
| 80 | + pair<int, int> ans; |
| 81 | + ans.first = max(op1, max(op2, op3)); |
| 82 | + ans.second = max(left.second, right.second) + 1; |
| 83 | + |
| 84 | + return ans; |
| 85 | + } |
| 86 | + |
| 87 | + int diameter(Node* root) { |
| 88 | + return diameterFast(root).first; |
| 89 | + } |
| 90 | +}; |
| 91 | +``` |
| 92 | +
|
| 93 | +## Problem Solution Explanation |
| 94 | +
|
| 95 | +```cpp |
| 96 | +class Solution { |
| 97 | + public: |
| 98 | + pair<int, int> diameterFast(Node* root) { |
| 99 | + // base case |
| 100 | + if(root == NULL) { |
| 101 | + pair<int, int> p = make_pair(0, 0); |
| 102 | + return p; |
| 103 | + }; |
| 104 | +``` |
| 105 | +- **Explanation**: If `root` is `NULL`, we return `{0, 0}`, where `0` represents both the diameter and height. For an empty tree, the diameter is `0`. |
| 106 | + |
| 107 | +```cpp |
| 108 | + pair<int, int> left = diameterFast(root -> left); |
| 109 | + pair<int, int> right = diameterFast(root -> right); |
| 110 | +``` |
| 111 | +- **Explanation**: Recursively calculate the diameter and height for the left and right subtrees. Each subtree returns a `pair<int, int>`, where `first` is the diameter and `second` is the height. |
| 112 | + |
| 113 | +```cpp |
| 114 | + int op1 = left.first; |
| 115 | + int op2 = right.first; |
| 116 | + int op3 = left.second + right.second + 1; |
| 117 | +``` |
| 118 | +- **Explanation**: |
| 119 | + - `op1` is the diameter of the left subtree. |
| 120 | + - `op2` is the diameter of the right subtree. |
| 121 | + - `op3` is the path that goes through the current node, calculated as the height of the left subtree plus the height of the right subtree plus one. |
| 122 | + |
| 123 | +```cpp |
| 124 | + pair<int, int> ans; |
| 125 | + ans.first = max(op1, max(op2, op3)); |
| 126 | + ans.second = max(left.second, right.second) + 1; |
| 127 | +``` |
| 128 | +- **Explanation**: |
| 129 | + - `ans.first` stores the maximum diameter, calculated as the maximum among `op1`, `op2`, and `op3`. |
| 130 | + - `ans.second` stores the height of the subtree rooted at `root`, which is `1 + max(left.second, right.second)`. |
| 131 | + |
| 132 | +```cpp |
| 133 | + return ans; |
| 134 | + } |
| 135 | +``` |
| 136 | +- **Explanation**: The `diameterFast` function returns a `pair` containing the maximum diameter and height for the current subtree. |
| 137 | + |
| 138 | +```cpp |
| 139 | + int diameter(Node* root) { |
| 140 | + return diameterFast(root).first; |
| 141 | + } |
| 142 | +}; |
| 143 | +``` |
| 144 | +- **Explanation**: `diameter(root).first` provides the diameter of the tree in terms of the number of nodes in the longest path. This is the final answer for the diameter of the binary tree. |
| 145 | +
|
| 146 | +### Step-by-Step Example Walkthrough |
| 147 | +
|
| 148 | +Consider the binary tree: |
| 149 | +
|
| 150 | +``` |
| 151 | + 1 |
| 152 | + / \ |
| 153 | + 2 3 |
| 154 | + / \ |
| 155 | + 4 5 |
| 156 | +``` |
| 157 | +
|
| 158 | +1. **Recursive Calculations**: |
| 159 | + - At each node, we calculate the diameter and height of both left and right subtrees. |
| 160 | +2. **Node 4 and Node 5**: |
| 161 | + - Both are leaf nodes, so the height is `1` and the diameter is `0`. |
| 162 | +3. **Node 2**: |
| 163 | + - Left subtree (node `4`) has a height of `1`, diameter of `0`. |
| 164 | + - Right subtree (node `5`) has a height of `1`, diameter of `0`. |
| 165 | + - Diameter at node `2` is `max(0, 0, 1 + 1 + 1) = 3`. |
| 166 | + - Height at node `2` is `1 + max(1, 1) = 2`. |
| 167 | +4. **Node 3**: |
| 168 | + - It has no children, so the height is `1` and the diameter is `0`. |
| 169 | +5. **Node 1**: |
| 170 | + - Left subtree (node `2`) has a height of `2`, diameter of `3`. |
| 171 | + - Right subtree (node `3`) has a height of `1`, diameter of `0`. |
| 172 | + - Diameter at node `1` is `max(3, 0, 2 + 1 + 1) = 4`. |
| 173 | + - Height at node `1` is `1 + max(2, 1) = 3`. |
| 174 | +
|
| 175 | +The overall diameter of the tree is `4`, which is the output of `diameter(root)`. |
| 176 | +
|
| 177 | +### Step 4: Time and Space Complexity |
| 178 | +
|
| 179 | +1. **Time Complexity**: **O(N)**, where `N` is the number of nodes in the tree. Each node is visited once, making the time complexity linear with respect to the tree’s size. |
| 180 | +2. **Space Complexity**: **O(H)**, where `H` is the height of the tree. This space is required for the recursive call stack. In the worst case (a skewed tree), it could be `N`, while in a balanced tree, it’s `log(N)`. |
0 commit comments