題目:
Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
思路:使用遞歸。
preorder[0]是整個tree的root,在inerder中定位root,左側的是leftTree或者leftchild,右側的是rightTree或者rightchild。
通過root在preorder中的位置以及左右樹的節點數,可以在preorder中分別定位各自的子樹的root。
舉個栗子:
preorder:A B D E C F inorder: D B E A F C
root爲A,inorder定位A後,劃分兩部分,左樹是D B E,右樹是F C,分別遞歸。
左樹的root可以通過preorder定位:原rootIndex+1即爲B,再把左樹劃分。
右樹的root在preorder的位置:原rootIndex+(左側樹的節點數)+1
遞歸的過程中,會維護inorder兩個index:left和right,left和right之間構成一個子樹,帶解析。
左/右樹的節點數,就是 left和right之間被root劃分後兩側的長度。(詳細見代碼理解)
代碼:
public class Construct_Binary_Tree_from_Preorder_and_Inorder_Traversal {
public int [] preorder;
public int [] inorder;
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder = preorder;
this.inorder = inorder;
if(preorder==null||preorder.length==0)
return null;
TreeNode root = new TreeNode(preorder[0]);
divideInorder(preorder[0], 0, root ,0,inorder.length-1);
return root;
}
private void divideInorder(int rootInt,int rootIntIndex,TreeNode root,int left,int right){
for(int i=left;i<=right;i++){
if(inorder[i]==rootInt){
if(i>left){
int leftRootInt = preorder[rootIntIndex+1];
TreeNode leftNode = new TreeNode(leftRootInt);
root.left=leftNode;
if(left+1<i){
//存在left子樹
divideInorder(leftRootInt,rootIntIndex+1,leftNode,left,i-1);
}
}
if(i<right){
int rightRootInt = preorder[rootIntIndex+i-left+1];
TreeNode rightNode = new TreeNode(rightRootInt);
root.right=rightNode;
if(i+1<right){
//存在right子樹
divideInorder(rightRootInt, rootIntIndex+i-left+1, rightNode, i+1, right);
}
}
}
}
}
}
思路(改進):用HashMap存放inorder信息,這樣在preorder中定位根節點後可以直接查詢map就可知root在inorder中的位置,不用再次遍歷。
public class Construct_Binary_Tree_from_Preorder_and_Inorder_Traversal {
public int [] preorder;
public Map<Integer,Integer> inorderMap = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder = preorder;
if(preorder==null||preorder.length==0)
return null;
for(int i=0;i<inorder.length;i++)
inorderMap.put(inorder[i], i);
TreeNode root = new TreeNode(preorder[0]);
divideInorder(preorder[0], 0, root ,0,inorder.length-1);
return root;
}
private void divideInorder(int rootInt,int rootIntIndex,TreeNode root,int left,int right){
int i = inorderMap.get(rootInt);
if(i>left){
int leftRootInt = preorder[rootIntIndex+1];
TreeNode leftNode = new TreeNode(leftRootInt);
root.left=leftNode;
if(left+1<i){
//存在left子樹
divideInorder(leftRootInt,rootIntIndex+1,leftNode,left,i-1);
}
}
if(i<right){
int rightRootInt = preorder[rootIntIndex+i-left+1];
TreeNode rightNode = new TreeNode(rightRootInt);
root.right=rightNode;
if(i+1<right){
//存在right子樹
divideInorder(rightRootInt, rootIntIndex+i-left+1, rightNode, i+1, right);
}
}
}
}