Skip to content

Commit 2747ba0

Browse files
authored
Create README.md
1 parent 0252262 commit 2747ba0

File tree

1 file changed

+236
-0
lines changed
  • 17 - Binary Tree Data Structure Problems/30 - Construct Tree From In-Order & Pre-Order

1 file changed

+236
-0
lines changed
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
<h1 align='center'>Construct - Tree - From - In-Order & Pre-Order</h1>
2+
3+
## Problem Statement
4+
5+
**Problem URL :** [Construct Tree From In-Order & Pre-Order](https://www.geeksforgeeks.org/problems/construct-tree-1/1?itm_source=geeksforgeeks&itm_medium=article&itm_campaign=practice_card)
6+
7+
![image](https://github.com/user-attachments/assets/81adc113-3a79-484c-a53d-fb1c3a7bebe0)
8+
![image](https://github.com/user-attachments/assets/419a1887-cea2-47a4-b02f-cf7e2c3ba9b9)
9+
10+
## Problem Explanation
11+
The problem is to construct a binary tree given two arrays:
12+
1. `inorder[]`: The inorder traversal of the tree.
13+
2. `preorder[]`: The preorder traversal of the tree.
14+
15+
### Example
16+
Consider the following arrays:
17+
- `inorder[] = {4, 2, 5, 1, 6, 3}`
18+
- `preorder[] = {1, 2, 4, 5, 3, 6}`
19+
20+
**Output**: The constructed binary tree should look like this:
21+
22+
```
23+
1
24+
/ \
25+
2 3
26+
/ \ \
27+
4 5 6
28+
```
29+
30+
### Constraints
31+
- The size of the input arrays will be between 1 and \(10^4\).
32+
- All values in the tree are unique.
33+
34+
### Edge Cases
35+
- If the tree is empty, both `inorder` and `preorder` will be empty arrays.
36+
- Trees with only one node should be handled properly.
37+
38+
## Step 2: Approach
39+
40+
### High-Level Overview
41+
To reconstruct the tree, we can utilize the properties of the preorder and inorder traversals:
42+
- In a preorder traversal, the first element is always the root of the tree.
43+
- In an inorder traversal, the elements to the left of the root form the left subtree, and the elements to the right form the right subtree.
44+
45+
### Step-by-Step Breakdown
46+
1. **Create a mapping** of each element in the inorder array to its index for quick lookup. This helps in identifying the left and right subtree boundaries quickly.
47+
2. **Recursively build the tree**:
48+
- Start from the first element of the preorder array as the root.
49+
- Use the mapping to find the index of the root in the inorder array.
50+
- Recursively build the left and right subtrees using the boundaries derived from the inorder array.
51+
52+
### Pseudocode
53+
```
54+
function buildTree(inorder[], preorder[], n):
55+
createMapping(inorder[], nodeToIndex)
56+
return solve(preorder[], 0, n-1)
57+
58+
function solve(preorder[], index, inOrderStart, inOrderEnd):
59+
if index >= n or inOrderStart > inOrderEnd:
60+
return NULL
61+
element = preorder[index]
62+
root = new Node(element)
63+
position = nodeToIndex[element]
64+
root.left = solve(preorder[], index+1, inOrderStart, position-1)
65+
root.right = solve(preorder[], index+1, position+1, inOrderEnd)
66+
return root
67+
```
68+
69+
## Problem Solution
70+
```cpp
71+
class Solution{
72+
public:
73+
74+
void createMapping(int in[], map<int, int> &nodeToIndex, int n){
75+
for(int i = 0; i < n; i++){
76+
nodeToIndex[in[i]] = i;
77+
}
78+
79+
}
80+
81+
Node* solve(int in[], int pre[], int &index, int inOrderStart, int inOrderEnd, int n, map<int, int> &nodeToIndex){
82+
if(index >= n || inOrderStart > inOrderEnd) return NULL;
83+
84+
int element = pre[index++];
85+
Node* root = new Node(element);
86+
87+
int position = nodeToIndex[element];
88+
89+
root->left = solve(in, pre, index, inOrderStart, position - 1, n, nodeToIndex);
90+
root->right = solve(in, pre, index, position + 1, inOrderEnd, n, nodeToIndex);
91+
92+
return root;
93+
}
94+
95+
Node* buildTree(int in[],int pre[], int n)
96+
{
97+
int preOrderIndex = 0;
98+
map<int, int> nodeToIndex;
99+
createMapping(in, nodeToIndex, n);
100+
101+
return solve(in, pre, preOrderIndex, 0, n-1, n, nodeToIndex);
102+
103+
}
104+
};
105+
```
106+
107+
## Problem Solution Explanation
108+
109+
Here's the code again for reference:
110+
111+
1. **Class Declaration**:
112+
```cpp
113+
class Solution {
114+
public:
115+
```
116+
- Defines a class named `Solution` that contains methods to solve the problem.
117+
118+
2. **Mapping Creation**:
119+
```cpp
120+
void createMapping(int in[], map<int, int> &nodeToIndex, int n) {
121+
```
122+
- This method creates a mapping of each value in the `inorder` array to its index.
123+
124+
3. **Filling the Map**:
125+
```cpp
126+
for (int i = 0; i < n; i++) {
127+
nodeToIndex[in[i]] = i;
128+
}
129+
```
130+
- Iterates through the `inorder` array and fills the `nodeToIndex` map with each element's value as the key and its index as the value.
131+
132+
4. **Recursive Solve Function**:
133+
```cpp
134+
Node* solve(int in[], int pre[], int &index, int inOrderStart, int inOrderEnd, int n, map<int, int> &nodeToIndex) {
135+
```
136+
- This method constructs the binary tree recursively.
137+
138+
5. **Base Case**:
139+
```cpp
140+
if (index >= n || inOrderStart > inOrderEnd) return NULL;
141+
```
142+
- Checks if the index has gone out of bounds or if the current subtree is invalid. If so, it returns `NULL`.
143+
144+
6. **Element Extraction**:
145+
```cpp
146+
int element = pre[index++];
147+
Node* root = new Node(element);
148+
```
149+
- Gets the current root element from the preorder array and creates a new `Node` for it. The index is incremented for the next recursive call.
150+
151+
7. **Finding Position in Inorder**:
152+
```cpp
153+
int position = nodeToIndex[element];
154+
```
155+
- Finds the index of the current root in the inorder array using the previously created mapping.
156+
157+
8. **Building Left Subtree**:
158+
```cpp
159+
root->left = solve(in, pre, index, inOrderStart, position - 1, n, nodeToIndex);
160+
```
161+
- Recursively calls `solve` to build the left subtree using the left part of the inorder array (from `inOrderStart` to `position - 1`).
162+
163+
9. **Building Right Subtree**:
164+
```cpp
165+
root->right = solve(in, pre, index, position + 1, inOrderEnd, n, nodeToIndex);
166+
```
167+
- Recursively calls `solve` to build the right subtree using the right part of the inorder array (from `position + 1` to `inOrderEnd`).
168+
169+
10. **Returning the Root**:
170+
```cpp
171+
return root;
172+
```
173+
- Returns the constructed subtree rooted at the current `root`.
174+
175+
11. **Building the Tree**:
176+
```cpp
177+
Node* buildTree(int in[], int pre[], int n) {
178+
int preOrderIndex = 0;
179+
map<int, int> nodeToIndex;
180+
createMapping(in, nodeToIndex, n);
181+
182+
return solve(in, pre, preOrderIndex, 0, n - 1, n, nodeToIndex);
183+
}
184+
```
185+
- Initializes the `preOrderIndex` to `0`, creates the mapping using `createMapping`, and starts the recursive process to build the tree.
186+
187+
## Step 4: Output Examples
188+
189+
Let's consider the following input:
190+
191+
### Input
192+
- `inorder[] = {4, 2, 5, 1, 6, 3}`
193+
- `preorder[] = {1, 2, 4, 5, 3, 6}`
194+
195+
### Execution Steps
196+
1. Call `buildTree` with the given `inorder` and `preorder`.
197+
2. The mapping created will be:
198+
```
199+
4 -> 0
200+
2 -> 1
201+
5 -> 2
202+
1 -> 3
203+
6 -> 4
204+
3 -> 5
205+
```
206+
3. The recursive calls will process as follows:
207+
- Root is `1`, left subtree: `2`, right subtree: `3`.
208+
- Further decomposing `2` gives us `4` and `5`.
209+
- Finally, `3` leads to `6`.
210+
211+
### Output
212+
The constructed tree will be:
213+
214+
```
215+
1
216+
/ \
217+
2 3
218+
/ \ \
219+
4 5 6
220+
```
221+
222+
## Step 5: Time and Space Complexity
223+
224+
### Time Complexity
225+
- **Mapping Creation**: \(O(n)\), where \(n\) is the number of nodes, since we are iterating over the inorder array once.
226+
- **Recursive Tree Construction**: Each node is processed once, leading to \(O(n)\).
227+
- **Total Time Complexity**: \(O(n)\) for the entire operation.
228+
229+
### Space Complexity
230+
- **Auxiliary Space**: The recursive call stack can go up to \(O(h)\), where \(h\) is the height of the tree. In the worst case (for a skewed tree), this can be \(O(n)\). The map for storing indices requires \(O(n)\).
231+
- **Total Space Complexity**: \(O(n)\) in the worst case.
232+
233+
### Summary
234+
The solution efficiently constructs a binary tree from given inorder and preorder traversals by leveraging the properties of these traversals and using a map for quick index lookups. The time complexity is linear, making this approach suitable for larger trees.
235+
236+
If you have any further questions or need additional clarification, feel free to ask!

0 commit comments

Comments
 (0)