Skip to content

Commit a86cbad

Browse files
authored
Create README.md
1 parent 8441b1e commit a86cbad

File tree

1 file changed

+201
-0
lines changed

1 file changed

+201
-0
lines changed
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
<h1 align='center'>Construct - Binary - Search - Tree - From - Pre-Order - Traversal</h1>
2+
3+
## Problem Statement
4+
5+
**Problem URL :** [Construct Binary Search Tree from Pre-order Traversal](https://leetcode.com/problems/construct-binary-search-tree-from-preorder-traversal/description/)
6+
7+
![image](https://github.com/user-attachments/assets/d2ba8a81-ea8f-4b55-bd0a-b899e844e88c)
8+
![image](https://github.com/user-attachments/assets/71c26f10-04c0-4b8f-ab76-8666557b9e72)
9+
10+
## Problem Explanation
11+
The problem asks us to construct a **Binary Search Tree (BST)** from the **preorder traversal** sequence. The preorder traversal visits the nodes in the following order: **Root -> Left Subtree -> Right Subtree**.
12+
13+
Given a sequence of values that represents the preorder traversal of a BST, we need to reconstruct the original BST.
14+
15+
#### Approach to Solve the Problem
16+
17+
1. **Understanding Preorder Traversal**:
18+
- In a BST, for any node:
19+
- All values in the **left subtree** are smaller than the node's value.
20+
- All values in the **right subtree** are greater than the node's value.
21+
- The first value in the preorder sequence is the **root** of the tree.
22+
- The subsequent values represent the preorder traversal of the left and right subtrees.
23+
24+
2. **Recursive Tree Construction**:
25+
- Starting from the first value (root), recursively construct the left and right subtrees:
26+
- The left subtree consists of values smaller than the root.
27+
- The right subtree consists of values greater than the root.
28+
- This recursive approach is governed by maintaining valid ranges (`mini` and `maxi`) for each node to ensure the BST property is upheld.
29+
30+
#### Example
31+
32+
Given the preorder traversal array:
33+
```
34+
[8, 5, 1, 7, 10, 12]
35+
```
36+
37+
- The first element (`8`) is the root of the BST.
38+
- The next value (`5`) is less than `8`, so it becomes the left child of `8`.
39+
- The next value (`1`) is less than `5`, so it becomes the left child of `5`.
40+
- The next value (`7`) is greater than `5` but less than `8`, so it becomes the right child of `5`.
41+
- The next value (`10`) is greater than `8`, so it becomes the right child of `8`.
42+
- The next value (`12`) is greater than `10`, so it becomes the right child of `10`.
43+
44+
The final tree looks like this:
45+
```
46+
8
47+
/ \
48+
5 10
49+
/ \ \
50+
1 7 12
51+
```
52+
53+
## Problem Solution
54+
```cpp
55+
/**
56+
* Definition for a binary tree node.
57+
* struct TreeNode {
58+
* int val;
59+
* TreeNode *left;
60+
* TreeNode *right;
61+
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
62+
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
63+
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
64+
* };
65+
*/
66+
class Solution {
67+
public:
68+
TreeNode* solve(vector<int>& preorder, int mini, int maxi, int &i){
69+
if(i >= preorder.size()) return NULL;
70+
71+
if(preorder[i] < mini || preorder[i] > maxi) return NULL;
72+
73+
TreeNode* root = new TreeNode(preorder[i++]);
74+
root -> left = solve(preorder, mini, root -> val, i);
75+
root -> right = solve(preorder, root -> val, maxi, i);
76+
77+
return root;
78+
}
79+
TreeNode* bstFromPreorder(vector<int>& preorder) {
80+
int mini = INT_MIN;
81+
int maxi = INT_MAX;
82+
83+
int i = 0;
84+
return solve(preorder, mini, maxi, i);
85+
}
86+
};
87+
```
88+
89+
## Problem Solution Explanation
90+
91+
```cpp
92+
class Solution {
93+
public:
94+
```
95+
- Defines the `Solution` class, which contains the function to solve the problem.
96+
97+
```cpp
98+
TreeNode* solve(vector<int>& preorder, int mini, int maxi, int &i){
99+
if(i >= preorder.size()) return NULL;
100+
```
101+
- `solve` is a helper function that will recursively build the BST.
102+
- `preorder` is the input array representing the preorder traversal.
103+
- `mini` and `maxi` represent the valid range of values for the current subtree.
104+
- `i` is the index pointer that tracks the current element in the `preorder` array.
105+
- If `i` exceeds the size of the array, it means we've processed all nodes, and `NULL` is returned (base case).
106+
107+
```cpp
108+
if(preorder[i] < mini || preorder[i] > maxi) return NULL;
109+
```
110+
- If the current value `preorder[i]` is outside the valid range (`mini` to `maxi`), it violates the BST property, so `NULL` is returned.
111+
112+
```cpp
113+
TreeNode* root = new TreeNode(preorder[i++]);
114+
```
115+
- A new node is created with the value `preorder[i]`.
116+
- The value of `i` is incremented to move to the next element for the next recursive call.
117+
118+
```cpp
119+
root -> left = solve(preorder, mini, root -> val, i);
120+
root -> right = solve(preorder, root -> val, maxi, i);
121+
```
122+
- The left subtree is built by calling `solve` with the range from `mini` to `root->val`. This ensures all left children are smaller than the root.
123+
- The right subtree is built by calling `solve` with the range from `root->val` to `maxi`. This ensures all right children are larger than the root.
124+
125+
```cpp
126+
return root;
127+
}
128+
```
129+
- Returns the root of the current subtree (the node created in this function).
130+
131+
```cpp
132+
TreeNode* bstFromPreorder(vector<int>& preorder) {
133+
int mini = INT_MIN;
134+
int maxi = INT_MAX;
135+
```
136+
- The main function `bstFromPreorder` initializes the range for the root node (`mini = INT_MIN` and `maxi = INT_MAX`), representing the entire valid range for the root value.
137+
- `i` is implicitly initialized to 0 at the start.
138+
139+
```cpp
140+
int i = 0;
141+
return solve(preorder, mini, maxi, i);
142+
}
143+
};
144+
```
145+
- Calls the helper function `solve` to start building the BST.
146+
- Returns the root of the constructed BST.
147+
148+
### Step 3: Example Walkthrough
149+
150+
Let's walk through an example:
151+
152+
Given the preorder traversal:
153+
```
154+
[8, 5, 1, 7, 10, 12]
155+
```
156+
157+
1. **Initial Call**:
158+
- `solve([8, 5, 1, 7, 10, 12], INT_MIN, INT_MAX, i)` is called with `i = 0`.
159+
- `preorder[0] = 8` is within the range `INT_MIN` to `INT_MAX`, so it becomes the root.
160+
- Increment `i` to 1.
161+
162+
2. **Left Subtree**:
163+
- Call `solve([8, 5, 1, 7, 10, 12], INT_MIN, 8, i)` with `i = 1`.
164+
- `preorder[1] = 5` is within the range `INT_MIN` to `8`, so it becomes the left child of `8`.
165+
- Increment `i` to 2.
166+
- Call `solve([8, 5, 1, 7, 10, 12], INT_MIN, 5, i)` to build the left subtree of `5`.
167+
168+
3. **Left Subtree of 5**:
169+
- `preorder[2] = 1` is within the range `INT_MIN` to `5`, so it becomes the left child of `5`.
170+
- Increment `i` to 3.
171+
- Call `solve([8, 5, 1, 7, 10, 12], INT_MIN, 1, i)` to build the left subtree of `1`. This returns `NULL`.
172+
173+
4. **Right Subtree of 5**:
174+
- Call `solve([8, 5, 1, 7, 10, 12], 5, 8, i)` to build the right subtree of `5`.
175+
- `preorder[3] = 7` is within the range `5` to `8`, so it becomes the right child of `5`.
176+
- Increment `i` to 4.
177+
178+
The tree continues building similarly for the rest of the values. The final BST is:
179+
```
180+
8
181+
/ \
182+
5 10
183+
/ \ \
184+
1 7 12
185+
```
186+
187+
### Step 4: Time and Space Complexity
188+
189+
1. **Time Complexity**:
190+
- The time complexity of the algorithm is **O(n)**, where `n` is the number of nodes in the tree. This is because each node is processed exactly once in the preorder traversal.
191+
192+
2. **Space Complexity**:
193+
- The space complexity is **O(h)**, where `h` is the height of the tree due to the recursive call stack. In the worst case (if the tree is skewed), `h` can be `n`, leading to a space complexity of **O(n)**.
194+
- Additionally, the space required to store the tree is **O(n)** because each node of the tree needs to be stored.
195+
196+
### Step 5: Recommendations for Students
197+
198+
- **Understand Preorder Traversal**: Preorder traversal is crucial in tree problems. Make sure you are comfortable with it, as it helps in various types of tree construction problems.
199+
- **Recursive Problem Solving**: This problem is a great example of using recursion for tree construction. Practice solving similar problems recursively, as it is a common approach for tree-related tasks.
200+
- **Edge Case Considerations**: Always think about edge cases such as an empty tree (when the input preorder is empty) or trees with only one node. Handling these gracefully is important in real-world coding.
201+

0 commit comments

Comments
 (0)