Skip to content

Commit

Permalink
Some langauage and spacing fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
edorado93 committed Feb 28, 2019
1 parent ebc2350 commit cb8f329
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,88 +1,88 @@
## Construct a Binary Tree from Inorder and Postorder Traversal
## Construct a Binary Tree from in-order and Postorder Traversal

<p>
<img align="center" alt="Question Screenshot" src="../../Images/Binary-Tree-from-Inorder-and-Postorder-Traversal/question.png">
<img align="center" alt="Question Screenshot" src="../../Images/Binary-Tree-from-in-order-and-Postorder-Traversal/question.png">
</p>

---

### Solution One :
### Solution One : Recursion

#### Motivation
We are given inorder and postorder traversal of a Binary Tree and we have to recreate the Binary Tree from the given traversals.
We are given in-order and postorder traversal of a Binary Tree and we have to recreate the Binary Tree from the given traversals.

**TIP:** To create a binary tree we need atleast two different traversals. A single traversal can correspond to many different tree structures.
**TIP:** To create a binary tree we need at least two different traversals. A single traversal can correspond to many different tree structures.

Let us understand how are we going to approach the problem by taking an example.

<p>
<img align="center" alt="Question Screenshot" src="./../../Images/Binary-Tree-from-Inorder-and-Postorder-Traversal/example-tree.png" width="600">
<img align="center" alt="Question Screenshot" src="./../../Images/Binary-Tree-from-in-order-and-Postorder-Traversal/example-tree.png" width="600">
</p>

Let us write the `Inorder` and `Postorder` traversal of the above tree.
Let us write the `in-order` and `Postorder` traversal of the above tree.

```
Inorder = [24,29,38,41,49,51,55,63,77]
in-order = [24,29,38,41,49,51,55,63,77]
Postorder = [29,24,41,38,51,55,77,63,49]
```
#### Observations derived from the Tree structure and it's traversals :

1. `root` of the tree will always be the last node in it's postorder traversal.
2. Nodes left to the `root` and Nodes right to the `root` appear in same fashion in it's inorder traversal. From the diagram Node(38) and Node(63) are left and right node of Root(49), they appear in same manner in the `inorder` traversal of the tree. They don't change their relative order with respect to it's parent.
2. Nodes left to the `root` and Nodes right to the `root` appear in same fashion in it's in-order traversal. From the diagram Node(38) and Node(63) are left and right node of Root(49), they appear in same manner in the `in-order` traversal of the tree. They don't change their relative ordering with respect to it's parent.

#### Algorithm
1. Find the last node in the `postorder` traversal.
2. Mark this as root for the current state.
3. Find the index of above node in the `inorder` traversal tree. So everything left to that `index` will be the left subtree and right to the `index` will be the right subtree.
4. If we carefully observe the part before `index` in `postorder` traversal and and the part after `index` in `postorder` corresponds to `postorder` traversal of left and right subtree respectively.
3. Find the index of above node in the `in-order` traversal tree. So everything left to that `index` will be the left subtree and right to the `index` will be the right subtree.
4. If we carefully observe the part before `index` in `postorder` traversal and the part after `index` in `postorder` traversal, they correspond to `postorder` traversal of left and right subtrees respectively.
5. Recursively repeat the the process from step 1-3 for left and right subtree.



#### Complexity Analysis
* Time Complexity: `O(N^3)` where `N` is the number of nodes. This is beacuse we are searching index of last node in `postorder` traversal in the `inorder` traversal of the tree for each recursive call and also creating the subarrays during the each recursive call.
* Time Complexity: `O(N^3)` where `N` is the number of nodes. This is because we are searching the index of last node in `postorder` traversal in the `in-order` traversal of the tree for each recursive call and also creating the sub-arrays in each recursive call. Linear search for the index and preparing sub-arrays for the recursive calls adds a lot of complexity to the solution. Hence the higher complexity.
* Space Complexity: `O(N)` where `N` is the number of nodes. The space is occupied by the recursion stack in this case.

---

### Solution Two :
### Solution Two : Optimized Recursion

#### Motivation
In solution one we were passing subarrays of `postorder` and `inorder` traversals of the tree in each recursive call. Since creating a subarray is also a `O(N)` operation, instead of creating a subarray we will pass indices of `inorder` and `postorder` array which will improve the performance.
In solution one we were passing subarrays of `postorder` and `in-order` traversals of the tree in each recursive call. Since creating a subarray is also a `O(N)` operation, instead of creating a subarray, we will pass indices of `in-order` and `postorder` array which will improve the performance.

#### Algorithm
1. Find the last node in the `postorder` traversal.
2. Mark this as root for the current state.
3. Find the index of above node in the `inorder` traversal tree. So everything left to that `index` will be the left subtree and right to the `index` will be the right subtree.
4. If we carefully observe the part before `index` in `postorder` traversal and and the part after `index` in `postorder` corresponds to `postorder` traversal of left and right subtree respectively.
3. Find the index of above node in the `in-order` traversal tree. So everything left to that `index` will be the left subtree and right to the `index` will be the right subtree.
4. If we carefully observe the part before `index` in `postorder` traversal and the part after `index` in `postorder` traversal, they correspond to `postorder` traversal of left and right subtrees respectively.
5. Recursively repeat the the process from step 1-3 for left and right subtree.
6. The only thing different from the previous solution is that now we use a pair of indices for each of the two arrays `postorder` and `in-order`. Rather than splitting the arrays themselves, we play around with the indices.

#### Complexity Analysis
* Time Complexity: `O(N^2)` where `N` is the number of nodes. This is beacuse we are searching index of last node in `postorder` traversal in the `inorder` traversal of the tree for each recursive call.
* Time Complexity: `O(N^2)` where `N` is the number of nodes. This is because we are searching index of last node in `postorder` traversal in the `in-order` traversal of the tree for each recursive call. The complexity reduced because we don't create any subarrays now. There is still some optimization that can be done and we will look at that in the next solution.
* Space Complexity: `O(N)` where `N` is the number of nodes. The space is occupied by the recursion stack in this case.

---

### Solution Three :
### Solution Three : Super Optimized Recursion!

#### Motivation
In all the above solutions we were trying to find the index of the element of the root which is an `O(N)` operation. We can reduce this complexity by keeping a map between `value` and `index` of each element of `inorder` traversal. This will reduce our search opeartion time to `O(1)` time.
In all the above solutions the index finding operation was simply a linear search which was `O(N)` operation. We can reduce this complexity by keeping a dictionary between `value` and `index` of each element of `in-order` traversal. This will reduce our search operation time to `O(1)` time. The reason we can do this is because the problem statement clearly states that the nodes in the in-order traversal are *unique* and hence such a mapping would bring down the search complexity from `O(N)` to `O(1)`.

#### Algorithm
1. Find the last node in the `postorder` traversal.
2. Mark this as root for the current state.
3. Find the index of above node in the `inorder` traversal tree. So everything left to that `index` will be the left subtree and right to the `index` will be the right subtree.
4. If we carefully observe the part before `index` in `postorder` traversal and and the part after `index` in `postorder` corresponds to `postorder` traversal of left and right subtree respectively.
5. Recursively repeat the the process from step 1-3 for left and right subtree.
1. Iterate over the `in-order` traversal array and prepare the dictionary that maps values to their indices.
2. Find the last node in the `postorder` traversal.
3. Mark this as root for the current state.
4. Find the index of above node in the `in-order` traversal tree using the dictionary we prepared in the first step. As before, everything left to that `index` will be the left subtree and right to the `index` will be the right subtree.
5. Recursively repeat the the process from step 2-4 for left and right subtree.

#### Complexity Analysis
* Time Complexity: `O(N)` where `N` is the number of nodes.
* Space Complexity: `O(N)` where `N` is the number of nodes. The space is occupied by the recursion stack in this case and hashmap of the `inorder` traversal.

* Space Complexity: `O(N)` where `N` is the number of nodes. The space is occupied by the recursion stack in this case and hash map of the `in-order` traversal.


#### Link to OJ
https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
https://leetcode.com/problems/construct-binary-tree-from-in-order-and-postorder-traversal/

---
Article contributed by [Arihant Sai](https://github.com/Arihant1467)
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,32 @@
# self.right = None

class Solution(object):

def __init__(self):
self.inorderMap = {}


def buildTree(self, inorder, postorder):
"""
:type inorder: List[int]
:type postorder: List[int]
:rtype: TreeNode
"""
self.inOrderMap = {inorder[i]:i for i in range(len(inorder))}
return self.build(inorder,0,len(inorder)-1,postorder,0,len(postorder)-1)
return self.build(inorder, 0, len(inorder) - 1, postorder, 0, len(postorder) - 1)


def build(self,inorder,iLeft,iRight,postorder,pLeft,pRight):



if pLeft>pRight:

if pLeft > pRight:
return None

rootVal = postorder[pRight]
rootNode = TreeNode(rootVal)

index = self.inOrderMap[rootVal]
rootNode.left = self.build(inorder,iLeft,index-1,postorder,pLeft,pLeft+(index-iLeft)-1)
rootNode.right = self.build(inorder,index+1,iRight,postorder,pLeft+(index-iLeft),pRight-1)

rootNode.left = self.build(inorder, iLeft, index - 1, postorder, pLeft, pLeft + (index - iLeft) - 1)
rootNode.right = self.build(inorder, index + 1, iRight, postorder, pLeft + (index - iLeft), pRight-1)

return rootNode

Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,30 @@
* };
*/
class Solution {

public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
return this->build(inorder,0,inorder.size()-1,postorder,0,postorder.size()-1);

return this->build(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);
}
TreeNode* build(vector<int>& inorder,int iLeft,int iRight,vector<int>& postorder,int pLeft,int pRight){
if(pLeft>pRight){

TreeNode* build(vector<int>& inorder, int iLeft, int iRight, vector<int>& postorder, int pLeft, int pRight){

if(pLeft > pRight){
return NULL;
}

int rootVal = postorder[pRight];
TreeNode* root = new TreeNode(rootVal);
auto it = std::find(inorder.begin()+iLeft,inorder.begin()+iRight,rootVal);

auto it = std::find(inorder.begin() + iLeft, inorder.begin() + iRight, rootVal);
int indexInInorder = std::distance(inorder.begin(), it);
root->left = this->build(inorder,iLeft,indexInInorder-1,postorder,pLeft,pLeft+(indexInInorder-iLeft)-1);
root->right = this->build(inorder,indexInInorder+1,iRight,postorder,pLeft+(indexInInorder-iLeft),pRight-1);

root->left = this->build(inorder, iLeft, indexInInorder - 1, postorder, pLeft, pLeft + (indexInInorder - iLeft) -1);
root->right = this->build(inorder, indexInInorder + 1, iRight, postorder, pLeft + (indexInInorder - iLeft), pRight -1);

return root;

}
};

};
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,28 @@
# self.right = None

class Solution(object):


def buildTree(self, inorder, postorder):
"""
:type inorder: List[int]
:type postorder: List[int]
:rtype: TreeNode
"""
return self.build(inorder,0,len(inorder)-1,postorder,0,len(postorder)-1)
return self.build(inorder, 0, len(inorder) - 1, postorder, 0, len(postorder) - 1)


def build(self,inorder,iLeft,iRight,postorder,pLeft,pRight):
if pLeft>pRight:

if pLeft > pRight:
return None

rootVal = postorder[pRight]
rootNode = TreeNode(rootVal)

index = inorder.index(rootVal)
rootNode.left = self.build(inorder,iLeft,index-1,postorder,pLeft,pLeft+(index-iLeft)-1)
rootNode.right = self.build(inorder,index+1,iRight,postorder,pLeft+(index-iLeft),pRight-1)

rootNode.left = self.build(inorder, iLeft, index - 1, postorder, pLeft, pLeft + (index - iLeft) -1)
rootNode.right = self.build(inorder, index + 1, iRight, postorder, pLeft + (index - iLeft), pRight - 1)

return rootNode

0 comments on commit cb8f329

Please sign in to comment.