Skip to content

Commit b688064

Browse files
authored
Create README.md
1 parent 14d546b commit b688064

File tree

1 file changed

+221
-0
lines changed

1 file changed

+221
-0
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
<h1 align='center'>Largest - BST</h1>
2+
3+
## Problem Statement
4+
5+
**Problem URL :** [Largest BST](https://www.geeksforgeeks.org/problems/largest-bst/1)
6+
7+
![image](https://github.com/user-attachments/assets/314a27bd-bb32-41e2-9f21-9ad20d71c9cb)
8+
![image](https://github.com/user-attachments/assets/fbb0650a-5d7c-46a8-be78-efc98144b6ea)
9+
10+
## Problem Explanation
11+
The task is to find the size of the largest Binary Search Tree (BST) within a binary tree.
12+
13+
- A **Binary Search Tree (BST)** is a binary tree where each node's value must be greater than all values in its left subtree and less than all values in its right subtree.
14+
- The "size" of a tree (or subtree) is the number of nodes it contains.
15+
16+
Given a binary tree, we need to find the largest subset of nodes that form a BST.
17+
18+
#### Example for Better Understanding
19+
20+
Consider the following binary tree:
21+
22+
```
23+
10
24+
/ \
25+
5 15
26+
/ \ \
27+
1 8 20
28+
```
29+
30+
Here, the subtree rooted at node `5` (`5 -> 1, 8`) forms a BST with size `3`. Similarly, the subtree rooted at `15` (`15 -> 20`) is also a BST with size `2`. The largest BST here is the subtree rooted at `5`, so the expected output is `3`.
31+
32+
33+
34+
### Step 2: Approach to Solve the Problem
35+
36+
#### Understanding the Approach
37+
38+
The idea is to recursively traverse each node in the binary tree and check whether the subtree rooted at that node forms a BST. While doing so:
39+
1. Track the minimum and maximum values in each subtree.
40+
2. Check the validity of the BST by comparing the values with left and right subtrees.
41+
42+
For each node:
43+
- If both the left and right subtrees are BSTs, and the current node's value is greater than the maximum value of the left subtree and less than the minimum value of the right subtree, then the subtree rooted at this node is a BST.
44+
- If it forms a BST, we calculate its size by summing up the sizes of left and right subtrees and adding one for the current node.
45+
46+
#### Example of Approach
47+
48+
In the binary tree:
49+
50+
```
51+
10
52+
/ \
53+
5 15
54+
/ \ \
55+
1 8 20
56+
```
57+
58+
- For each node, recursively check if its left and right children form valid BSTs.
59+
- Track the minimum and maximum values in each subtree to determine if the current subtree satisfies BST properties.
60+
- For example, at node `5`, both children (`1` and `8`) satisfy the BST properties, so we calculate its size as `3`.
61+
62+
## Problem Solution
63+
```cpp
64+
class info {
65+
public:
66+
int mini;
67+
int maxi;
68+
bool isBST;
69+
int size;
70+
};
71+
72+
class Solution {
73+
public:
74+
info getLargestBSTInfo(Node* root, int &ans) {
75+
if (root == NULL) return info{INT_MAX, INT_MIN, true, 0};
76+
77+
info left = getLargestBSTInfo(root->left, ans);
78+
info right = getLargestBSTInfo(root->right, ans);
79+
80+
info currNode;
81+
currNode.size = left.size + right.size + 1;
82+
currNode.maxi = max(root->data, right.maxi);
83+
currNode.mini = min(root->data, left.mini);
84+
85+
if (left.isBST && right.isBST && (root->data > left.maxi && root->data < right.mini)) {
86+
currNode.isBST = true;
87+
} else {
88+
currNode.isBST = false;
89+
}
90+
91+
if (currNode.isBST) ans = max(ans, currNode.size);
92+
93+
return currNode;
94+
}
95+
96+
int largestBst(Node* root) {
97+
int maxSize = 0;
98+
getLargestBSTInfo(root, maxSize);
99+
return maxSize;
100+
}
101+
};
102+
103+
```
104+
105+
## Problem Solution Explanation
106+
107+
```cpp
108+
class info {
109+
public:
110+
int mini;
111+
int maxi;
112+
bool isBST;
113+
int size;
114+
};
115+
```
116+
117+
- **Purpose of `info` Class**: This helper class stores information about each node in the binary tree.
118+
- `mini` and `maxi` track the minimum and maximum values of the subtree rooted at each node.
119+
- `isBST` is a flag to determine if the subtree rooted at the node forms a BST.
120+
- `size` represents the number of nodes in the subtree.
121+
122+
```cpp
123+
class Solution {
124+
public:
125+
info getLargestBSTInfo(Node* root, int &ans) {
126+
if(root == NULL) return info{INT_MAX, INT_MIN, true, 0};
127+
```
128+
129+
- **Base Case**: If `root` is `NULL`, return an `info` object for an empty subtree:
130+
- `mini = INT_MAX` and `maxi = INT_MIN` ensure that they don’t interfere with comparisons.
131+
- `isBST = true` because an empty tree is considered a BST.
132+
- `size = 0` as there are no nodes in an empty subtree.
133+
134+
```cpp
135+
info left = getLargestBSTInfo(root->left, ans);
136+
info right = getLargestBSTInfo(root->right, ans);
137+
```
138+
139+
- **Recursive Calls**: We recursively call `getLargestBSTInfo` on the left and right children to gather information on each subtree.
140+
141+
```cpp
142+
info currNode;
143+
currNode.size = left.size + right.size + 1;
144+
currNode.maxi = max(root->data, right.maxi);
145+
currNode.mini = min(root->data, left.mini);
146+
```
147+
148+
- **Current Node Calculation**:
149+
- `currNode.size` is the size of the subtree rooted at the current node, calculated by summing up the sizes of the left and right subtrees and adding one for the current node itself.
150+
- `currNode.maxi` and `currNode.mini` update the maximum and minimum values within the subtree.
151+
152+
```cpp
153+
if (left.isBST && right.isBST && (root->data > left.maxi && root->data < right.mini)) {
154+
currNode.isBST = true;
155+
} else {
156+
currNode.isBST = false;
157+
}
158+
```
159+
160+
- **BST Check**: We check if both left and right subtrees are BSTs and if the current node satisfies the BST property with its children. If true, `currNode.isBST` is set to true.
161+
162+
```cpp
163+
if (currNode.isBST) ans = max(ans, currNode.size);
164+
```
165+
166+
- **Update Largest BST Size**: If `currNode` is a BST, we update the answer with the maximum size found so far.
167+
168+
```cpp
169+
return currNode;
170+
}
171+
```
172+
173+
- **Return `currNode`**: Return the `info` object for the current node to be used in calculations up the recursive stack.
174+
175+
```cpp
176+
int largestBst(Node* root) {
177+
int maxSize = 0;
178+
getLargestBSTInfo(root, maxSize);
179+
return maxSize;
180+
}
181+
};
182+
```
183+
184+
- **Main Function (`largestBst`)**:
185+
- This function initializes `maxSize` to zero and calls `getLargestBSTInfo`.
186+
- Finally, it returns the largest BST size found.
187+
188+
189+
190+
### Step 4: Example Walkthrough
191+
192+
Let's apply this on our sample tree:
193+
194+
```
195+
10
196+
/ \
197+
5 15
198+
/ \ \
199+
1 8 20
200+
```
201+
202+
1. **Node `1`** and `8`: Both are leaf nodes and satisfy BST conditions.
203+
2. **Node `5`**: Receives info from `1` and `8` (both BSTs), checks `5 > 1` and `5 < 8`, confirming it as a BST with size `3`.
204+
3. **Node `15`** and `20`: Both satisfy BST conditions.
205+
4. **Node `10`**: Combines info from `5` and `15`, confirms it as BST with size `6`.
206+
207+
Output: The largest BST has `size = 3` (rooted at `5`).
208+
209+
210+
### Step 5: Time and Space Complexity
211+
212+
1. **Time Complexity**: `O(N)` where `N` is the number of nodes. Each node is visited once, gathering information on its subtrees.
213+
2. **Space Complexity**: `O(H)`, where `H` is the height of the tree due to the recursion stack.
214+
215+
216+
### Step 6: Recommendations
217+
218+
- **Practice Recursive BST Validation**: This problem reinforces understanding of how BST properties work.
219+
- **Explore Edge Cases**: Test with trees that contain duplicate values, single nodes, and completely balanced trees to deepen understanding.
220+
221+
This step-by-step explanation should help you grasp the code flow and logic for finding the largest BST in a binary tree.

0 commit comments

Comments
 (0)