|
| 1 | +<h1 align='center'>Maximum - Sum - BST in - Binary - Tree</h1> |
| 2 | + |
| 3 | +## Problem Statement |
| 4 | + |
| 5 | +**Problem URL :** [Maximum Sum BST in Binary Tree](https://leetcode.com/problems/maximum-sum-bst-in-binary-tree/) |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | +## Problem Explanation |
| 11 | +The problem is to find the **maximum sum** of a **binary search tree (BST)** in a given binary tree. The challenge is to find the largest BST (in terms of the sum of its values) within the binary tree, and return the sum of the values of the largest BST. |
| 12 | + |
| 13 | +#### **Binary Tree and Binary Search Tree (BST):** |
| 14 | +- **Binary Tree**: A tree in which each node has at most two children (left and right). |
| 15 | +- **Binary Search Tree (BST)**: A binary tree where the value of each node must be greater than the values in its left subtree and smaller than the values in its right subtree. |
| 16 | + |
| 17 | +#### **Goal:** |
| 18 | +- You are given a binary tree, and you need to identify all the BSTs in it. |
| 19 | +- For each BST found, you will calculate the sum of its node values. |
| 20 | +- Return the sum of the largest BST in the binary tree. |
| 21 | + |
| 22 | +### **Approach to Solve the Problem:** |
| 23 | +We can approach this problem using **post-order traversal** (visiting left subtree, right subtree, and then the root node), combined with information tracking for each subtree to determine if it is a valid BST and calculate the sum. Here’s how: |
| 24 | + |
| 25 | +1. **Start with the root node**: The root of the tree can be the root of a BST, or it can be part of a larger BST. Our goal is to check every node and determine if it is the root of a valid BST. |
| 26 | +2. **Use recursive DFS**: We need to explore the left and right subtrees first, and then combine their results to determine whether the current node and its subtrees form a valid BST. |
| 27 | +3. **Track information**: |
| 28 | + - `mini`: The minimum value in the subtree. |
| 29 | + - `maxi`: The maximum value in the subtree. |
| 30 | + - `isBST`: Whether the current subtree is a valid BST. |
| 31 | + - `size`: The number of nodes in the subtree. |
| 32 | + - `sum`: The sum of the values in the subtree. |
| 33 | +4. **Conditions to form a valid BST**: |
| 34 | + - The left subtree is a valid BST and its maximum value is less than the root's value. |
| 35 | + - The right subtree is a valid BST and its minimum value is greater than the root's value. |
| 36 | + - The root’s value must lie between the maximum value of the left subtree and the minimum value of the right subtree. |
| 37 | +5. **Calculate the maximum sum**: Each time a valid BST is found, we check its sum and update the maximum sum if necessary. |
| 38 | + |
| 39 | +#### **Example:** |
| 40 | +Consider the binary tree: |
| 41 | + |
| 42 | +``` |
| 43 | + 1 |
| 44 | + / \ |
| 45 | + 4 3 |
| 46 | + / \ \ |
| 47 | + 2 4 5 |
| 48 | + \ |
| 49 | + 6 |
| 50 | +``` |
| 51 | + |
| 52 | +- Subtrees that are valid BSTs: |
| 53 | + - The subtree rooted at `4` with nodes `{4, 2, 4}` is a valid BST. |
| 54 | + - The subtree rooted at `3` with nodes `{3, 5, 6}` is a valid BST. |
| 55 | + |
| 56 | +- The largest BST is the subtree rooted at `3`, with nodes `{3, 5, 6}` and sum = `3 + 5 + 6 = 14`. |
| 57 | + |
| 58 | +So, the expected output is `14`. |
| 59 | + |
| 60 | +## Problem Solution |
| 61 | +```cpp |
| 62 | +/** |
| 63 | + * Definition for a binary tree node. |
| 64 | + * struct TreeNode { |
| 65 | + * int val; |
| 66 | + * TreeNode *left; |
| 67 | + * TreeNode *right; |
| 68 | + * TreeNode() : val(0), left(nullptr), right(nullptr) {} |
| 69 | + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} |
| 70 | + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} |
| 71 | + * }; |
| 72 | + */ |
| 73 | + |
| 74 | +class nodeInfo{ |
| 75 | + public: |
| 76 | + int mini; |
| 77 | + int maxi; |
| 78 | + bool isBST; |
| 79 | + int size; |
| 80 | + int sum; |
| 81 | +}; |
| 82 | +class Solution { |
| 83 | +public: |
| 84 | + nodeInfo getLargestBSTSize(TreeNode* root, int &ans){ |
| 85 | + if(root == NULL) return nodeInfo{INT_MAX, INT_MIN, true, 0, 0}; |
| 86 | + |
| 87 | + nodeInfo left = getLargestBSTSize(root -> left, ans); |
| 88 | + nodeInfo right = getLargestBSTSize(root -> right, ans); |
| 89 | + |
| 90 | + nodeInfo currentNode; |
| 91 | + currentNode.size = left.size + right.size + 1; |
| 92 | + currentNode.sum = left.sum + right.sum + root -> val; |
| 93 | + currentNode.mini = min(root -> val, left.mini); |
| 94 | + currentNode.maxi = max(root -> val, right.maxi); |
| 95 | + |
| 96 | + if(left.isBST && right.isBST && (root -> val > left.maxi && root -> val < right.mini)){ |
| 97 | + currentNode.isBST = true; |
| 98 | + ans = max(ans, currentNode.sum); |
| 99 | + }else{ |
| 100 | + currentNode.isBST = false; |
| 101 | + } |
| 102 | + |
| 103 | + return currentNode; |
| 104 | + } |
| 105 | + |
| 106 | + int maxSumBST(TreeNode* root) { |
| 107 | + int max_sum = 0; |
| 108 | + getLargestBSTSize(root, max_sum); |
| 109 | + return max_sum; |
| 110 | + } |
| 111 | +}; |
| 112 | +``` |
| 113 | +
|
| 114 | +## Problem Solution Explanation |
| 115 | +
|
| 116 | +Now, let’s go through the code line by line to understand how it works. |
| 117 | +
|
| 118 | +```cpp |
| 119 | +class nodeInfo { |
| 120 | +public: |
| 121 | + int mini; // Minimum value in the subtree |
| 122 | + int maxi; // Maximum value in the subtree |
| 123 | + bool isBST; // Whether the subtree is a valid BST |
| 124 | + int size; // Number of nodes in the subtree |
| 125 | + int sum; // Sum of values in the subtree |
| 126 | +}; |
| 127 | +``` |
| 128 | +- **`nodeInfo` Class**: This class is used to store the details of each subtree. It stores: |
| 129 | + - `mini`: Minimum value in the subtree. |
| 130 | + - `maxi`: Maximum value in the subtree. |
| 131 | + - `isBST`: Whether the subtree is a valid BST. |
| 132 | + - `size`: Number of nodes in the subtree. |
| 133 | + - `sum`: Sum of values in the subtree. |
| 134 | + |
| 135 | +```cpp |
| 136 | +class Solution { |
| 137 | +public: |
| 138 | + nodeInfo getLargestBSTSize(TreeNode* root, int &ans) { |
| 139 | + if (root == NULL) return nodeInfo{INT_MAX, INT_MIN, true, 0, 0}; |
| 140 | +``` |
| 141 | +- **`getLargestBSTSize` Function**: This function computes the largest BST in the subtree rooted at `root`. |
| 142 | + - If `root == NULL`, it returns an empty subtree with: |
| 143 | + - `mini = INT_MAX` (to ensure any node will be greater). |
| 144 | + - `maxi = INT_MIN` (to ensure any node will be smaller). |
| 145 | + - `isBST = true` because `NULL` is a valid BST. |
| 146 | + - `size = 0` (no nodes). |
| 147 | + - `sum = 0`. |
| 148 | +
|
| 149 | +```cpp |
| 150 | + nodeInfo left = getLargestBSTSize(root->left, ans); |
| 151 | + nodeInfo right = getLargestBSTSize(root->right, ans); |
| 152 | +``` |
| 153 | +- The function recursively gets the `nodeInfo` for the left and right subtrees. |
| 154 | + |
| 155 | +```cpp |
| 156 | + nodeInfo currentNode; |
| 157 | + currentNode.size = left.size + right.size + 1; |
| 158 | + currentNode.sum = left.sum + right.sum + root->val; |
| 159 | + currentNode.mini = min(root->val, left.mini); |
| 160 | + currentNode.maxi = max(root->val, right.maxi); |
| 161 | +``` |
| 162 | +- **`currentNode` Information**: This stores the information of the current subtree rooted at `root`. |
| 163 | + - `size`: Total size of the subtree, which is the size of the left subtree, right subtree, and the current node. |
| 164 | + - `sum`: Sum of all node values in the subtree. |
| 165 | + - `mini`: The minimum value in the current subtree (minimum of `root->val` and the left subtree). |
| 166 | + - `maxi`: The maximum value in the current subtree (maximum of `root->val` and the right subtree). |
| 167 | + |
| 168 | +```cpp |
| 169 | + if (left.isBST && right.isBST && (root->val > left.maxi && root->val < right.mini)) { |
| 170 | + currentNode.isBST = true; |
| 171 | + ans = max(ans, currentNode.sum); |
| 172 | + } else { |
| 173 | + currentNode.isBST = false; |
| 174 | + } |
| 175 | +``` |
| 176 | +- **Validating the BST**: |
| 177 | + - If both left and right subtrees are valid BSTs and the current node’s value is greater than the maximum value in the left subtree and smaller than the minimum value in the right subtree, then the current subtree is a valid BST. |
| 178 | + - If it is a valid BST, we update the `ans` variable with the sum of the current BST if it is larger than the previously found BST. |
| 179 | +
|
| 180 | +```cpp |
| 181 | + return currentNode; |
| 182 | + } |
| 183 | +``` |
| 184 | +- The function returns the information of the current subtree, which will be used by the parent node in the recursive call. |
| 185 | + |
| 186 | +```cpp |
| 187 | + int maxSumBST(TreeNode* root) { |
| 188 | + int max_sum = 0; |
| 189 | + getLargestBSTSize(root, max_sum); |
| 190 | + return max_sum; |
| 191 | + } |
| 192 | +}; |
| 193 | +``` |
| 194 | +- **`maxSumBST` Function**: This is the main function. It initializes `max_sum` to 0 and calls the helper function `getLargestBSTSize` to find the largest BST and update the `max_sum`. Finally, it returns the value of `max_sum`. |
| 195 | +
|
| 196 | +### Step 3: Examples and Explanation |
| 197 | +
|
| 198 | +Let’s go over the examples: |
| 199 | +
|
| 200 | +#### Example 1: |
| 201 | +**Input**: |
| 202 | +``` |
| 203 | + 1 |
| 204 | + / \ |
| 205 | + 4 3 |
| 206 | + / \ \ |
| 207 | + 2 4 5 |
| 208 | + \ |
| 209 | + 6 |
| 210 | +``` |
| 211 | +- The largest BST is the subtree rooted at `3` with nodes `{3, 5, 6}`. |
| 212 | +- Sum = `3 + 5 + 6 = 14`. |
| 213 | +
|
| 214 | +**Output**: |
| 215 | +`14` |
| 216 | +
|
| 217 | +#### Example 2: |
| 218 | +**Input**: |
| 219 | +``` |
| 220 | + 10 |
| 221 | + / \ |
| 222 | + 5 15 |
| 223 | + / \ \ |
| 224 | + 1 8 7 |
| 225 | +``` |
| 226 | +- The largest BST is the subtree rooted at `5` with nodes `{5, 1, 8}`. |
| 227 | +- Sum = `5 + 1 + 8 = 14`. |
| 228 | +
|
| 229 | +**Output**: |
| 230 | +`14` |
| 231 | +
|
| 232 | +### Step 4: Time and Space Complexity |
| 233 | +
|
| 234 | +- **Time Complexity**: O(N), where N is the number of nodes in the binary tree. This is because we visit each node once during the post-order traversal. |
| 235 | +- **Space Complexity**: O(H), where H is the height of the tree. This is due to the recursive stack used during the traversal, which can go as deep as the height of the tree. In the worst case (a skewed tree), this can be O(N). |
| 236 | +
|
| 237 | +### Step 5: Recommendations for Students |
| 238 | +
|
| 239 | +1. **Understand the BST properties**: Make sure you are comfortable with the properties of a binary search tree. This problem is fundamentally about verifying if a subtree is a BST and calculating its sum. |
| 240 | +2. **Recursive thinking**: This problem involves recursion, so practice breaking down problems into smaller subproblems (subtrees in this case). |
| 241 | +3. **Practice with variations**: Once you're comfortable with this problem, try solving variations, such as finding the largest BST with a given number of nodes or modifying the approach to handle different tree structures. |
| 242 | +4. **Edge Cases**: Don’t forget to consider edge cases, such as: |
| 243 | + - An empty tree (null root). |
| 244 | + - Trees where no valid BSTs exist (answer should be 0). |
| 245 | + - Trees with only one node ( |
| 246 | +
|
| 247 | +valid BST). |
| 248 | +
|
0 commit comments