106. Construct Binary Tree from Inorder and Postorder Traversal
106. Construct Binary Tree from Inorder and Postorder Traversal
Given inorder and postorder traversal of a tree, construct the binary tree.
Note: You may assume that duplicates do not exist in the tree.
For example, given
inorder = [9,3,15,20,7]
postorder = [9,15,7,20,3]
Return the following binary tree:
3
/ \
9 20
/ \
15 7
My Solutions:
1。recursive
根据postorder(left-right-root)和inorder(left-root-right)的特点,可以得到以下规律:
初始的时候,root 在postorder array的最末端(postE),postE代表postorder array里最后一个元素
因为树里所有的元素都不同,可以通过val在inorder array里找到root的index
root's right 在postorder array里root的前一个位置(postE-1) 。并且一定在inorder array里root的后方,换句话说,inorder array里root的右边都是右边的树,root将inorder array 一分为二。所以此时的inS(代表inorder的起始位置)是index+1, 此时的inE(代表inorder的终点位置)还是inE。
root's left一定是在inorder array里root的前方,换句话说,inorder array里root的左边都是左边的树,root将inorder array 一分为二。所以此时的inS(代表inorder的起始位置)还是inS, 此时的inE(代表inorder的终点位置)是index-1。
最复杂的就是此时postE应该是什么。root's left一定是在postorder array 里root的前方, 并且是所有右边树的前方。
(inE - index ): 是此时root右边的所有节点的个数
此时的postE是此时的root在postorder array里的位置。因此在post order里,root's left 会在现在postE减去此时root右边的所有节点的个数,再多减1(root本身)
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (postorder.length == 0) return null;
return helper(postorder.length - 1, 0, inorder.length - 1, inorder, postorder);
}
public TreeNode helper(int postE, int inS, int inE, int[] inorder, int[] postorder) {
if (postE < 0 || inS > inE) return null;
TreeNode root = new TreeNode(postorder[postE]);
int index = 0; //index of root in inorder
for (int i = inS; i <= inE; i++) {
if (inorder[i] == root.val) index = i;
}
//the right child of root is the root's prev in postorder, and must be in the root's right side in the inorder
root.right = helper(postE - 1, index + 1, inE, inorder, postorder);
//the left child of root is among the root's prev in postorder,
//so that the postE = postE(index of current root in postorder) - 1 - (inE - index : the number of nodes on the right of current root)
//and must be in the root's left side in the inorder
root.left = helper(postE - 1 - (inE - index), inS, index - 1, inorder, postorder);
return root;
}
}
2。iterative
对于一个root来说,root将inorder array一分为二。因此,先存一个inorder array's (value : index) in a map。用stack先存一个root,然后把postorder 里的数字从后往前遍历,建造节点node。如果此时value的index
大于 stack.peek的节点的index,说明当前node是peek到的数字的右节点。连上节点。最后把当前node塞入stack
小于 stack.peek的节点的index,说明当前node在某个节点的左边。为了找到当前node的root,一直pop stack同时保存弹出来的node,直到peek看到节点index 不再比当前index大。最后保存的那个节点就是当前的root。连上节点。最后把当前node塞入stack
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (postorder.length == 0) return null;
// save inorder array's (value : index) in a map
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < inorder.length; i++) map.put(inorder[i], i);
Stack<TreeNode> stack = new Stack<>();
TreeNode root = new TreeNode(postorder[postorder.length - 1]);
stack.push(root);
for (int i = postorder.length - 2; i >= 0; i--) {
int value = postorder[i];
TreeNode node = new TreeNode(value); // 这个node是一个root
if (map.get(value) > map.get(stack.peek().val)) { // node should be on the right of stack's top node
stack.peek().right = node;
} else { //node should be on the left of stack's top node
TreeNode parent = null;
while (!stack.isEmpty() && map.get(value) < map.get(stack.peek().val)) { //keep poping up node until find the root of current node && node should be on the left of stack's top node
parent = stack.pop();
}
parent.left = node;
}
stack.push(node);
}
return root;
}
Last updated