思路:觀察發現,首先從preorder獲得根結點,從inorder找到根結點所在位置index,inorder[i]之前的內容爲左子樹,之後的內容爲右子樹。
left和right記錄的是preorder的邊界,start和end記錄的是inorder的邊界
public TreeNode buildTree(int[] preorder, int[] inorder) {
TreeNode root=buildTreeCore(preorder, 0, preorder.length, inorder, 0, inorder.length);
return root;
}
public TreeNode buildTreeCore(int[] preorder, int left, int right, int[] inorder, int start, int end) {
if(left>right||start>end||left>=preorder.length||start>=inorder.length) return null;
if(start==end) return new TreeNode(inorder[start]);
TreeNode root=new TreeNode(preorder[left]);
//採用循環尋找根結點在inorder中的位置
for(int i=start;i<end;i++){
if(inorder[i]==preorder[left]){
//計算左子樹結點數量
int leftSize=i-start;
if(leftSize!=0){
//遞歸重構左子樹
root.left=buildTreeCore(preorder, left+1, left+leftSize, inorder, start, i);
}
//遞歸重構右子樹
int rightRoot=left+leftSize+1;
root.right=buildTreeCore(preorder, rightRoot, right, inorder, i+1, end);
break;
}
}
return root;
}
優化:因爲樹結點不會重複,所以可以將inorder結點與下標使用hashmap儲存起來,可以提升效率。
public TreeNode buildTree(int[] preorder, int[] inorder) {
HashMap<Integer,Integer> map=new HashMap<>();
for(int i=0;i<inorder.length;i++){
map.put(inorder[i],i);
}
TreeNode root=buildTreeCore(preorder, 0, preorder.length, inorder, 0, inorder.length, map);
return root;
}
public TreeNode buildTreeCore(int[] preorder, int left, int right, int[] inorder, int start, int end, HashMap<Integer,Integer> map) {
if(left>right||start>end||left>=preorder.length||start>=inorder.length) return null;
if(start==end) return new TreeNode(inorder[start]);
TreeNode root=new TreeNode(preorder[left]);
//直接獲取下標,省去循環的時間消耗
int index=map.get(preorder[left]);
int leftSize=index-start;
if(leftSize!=0){
root.left=buildTreeCore(preorder, left+1, left+leftSize, inorder, start, index, map);
}
int rightRoot=left+leftSize+1;
root.right=buildTreeCore(preorder, rightRoot, right, inorder, index+1, end, map);
return root;
}