This question takes me too much time. Actually, it is not very difficult, but I am not very familiar with preorder and inorder traversal of binary tree, since I learned these things long long ago. Anyway, this is a good time for refreshing tree traversal. Before my trip to L.A., the code was almost done, but got TLE. Yesterday, I started working on it again, and then find out one mistake I made before.
Now, time for explanation. Firstly, what we should do is to find out left child and right child for each node. We can build the tree if we knew the left and right child of each node, can't we? Since preorder traversal is mid-left-right, if we find one node in preorder array has left child, then its next node in preorder array should be its left child. So the key for left child is to determine whether it has left child. Previously, I wrote a method to do this thing. This method check inorder array from index 0, until current node is met, to find whether there exists unvisited node before current node in inorder array. Because inorder array traverse tree in left-mid-right order, nodes before current node must stand in the left-hand side of current node. If found, next value in preorder is current's left child, if not, just need to find right child. One key point we should keep in mind is that the nodes before current node in inorder array stand in the left side, but these nodes might be "higher" or "lower" than current node, "higher" ones are "parent" nodes, which have been visited. Only lower ones, those unvisited, can be left child of current node. That is why a hashmap is applied in my code. Luckily, values in arrays are unique. This should be designed for this problem.
For right child, we can add number of nodes in left subtree to current index in preorder array, then we should know where right child locates. Because in preorder array, we visited left subtree first, then visit right child. If sum is larger than length of array, or node in such index has been visited, it means current node has no right child.
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
// preorder is used to finally determine which is left or right child, inorder is helper
if(preorder.length == 0 || inorder.length == 0 || preorder.length != inorder.length) return null;
HashMap<Integer,TreeNode> visitedNode = new HashMap<Integer,TreeNode>();
TreeNode root = new TreeNode(preorder[0]);
visitedNode.put(root.val,root);
for(int i = 0; i < preorder.length-1 && visitedNode.size()!= preorder.length; i ++){
int crntVal = preorder[i];
TreeNode newNode;
if(!visitedNode.containsKey(crntVal)){
newNode = new TreeNode(crntVal);
visitedNode.put(crntVal,newNode);
}
else{
newNode = visitedNode.get(crntVal);
}
int numIn = findNumLeft(inorder,crntVal,visitedNode);// findNumLeft find out how many left
//children nodes this node has,
// i.e. how many nodes contained in the left subtree of current node
if(numIn > 0){
TreeNode leftChild = new TreeNode(preorder[i+1]);
newNode.left = leftChild;
visitedNode.put(leftChild.val,leftChild);
int rightIdx = numIn + i+1;
if(rightIdx >= preorder.length || visitedNode.containsKey(preorder[rightIdx])) newNode.right = null;
else {
TreeNode rightChild = new TreeNode(preorder[rightIdx]);
newNode.right = rightChild;
visitedNode.put(rightChild.val,rightChild);
}
}
else{// if no left child
newNode.left = null;
int rightIdx = numIn + i+1;
if(rightIdx >= preorder.length || visitedNode.containsKey(preorder[rightIdx])) newNode.right = null;// in this case, no right child
else{
TreeNode rightChild = new TreeNode(preorder[rightIdx]);
newNode.right = rightChild;
visitedNode.put(rightChild.val,rightChild);
}
}
}
return root;
}
public int findNumLeft(int[] arr, int val,HashMap<Integer,TreeNode> visitedNode){
int count = 0;
for(int i = 0; i < arr.length; i++){
if(!visitedNode.containsKey(arr[i])) count ++;
if(arr[i] == val) return count;
}
return count;
}
// public boolean hasLeft(int[] inorder, TreeNode node,HashMap<Integer,TreeNode> visitedNode){
// //int idx = find(inorder,node.val);
// for(int i = 0 ; inorder[i]!=node.val; i++){
// if(!visitedNode.containsKey(inorder[i])) return true;
// }
// return false;
// }
}
No comments:
Post a Comment