題目描述
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重復的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹并返回。
解題思路
二叉樹,想到還是遞歸:重建二叉樹,重建根節點的左右節點,對于左右節點來說又是重建根...........
已知前序遍歷,中序遍歷,來重建二叉樹。
- 前序序列的首節點是當前序列重構二叉樹的根節點
- 根據根節點來劃分中序序列,分為左右兩部分。
- 根據中序序列劃分,在劃分前序序列,分為左右兩部分的子前序序列
給定:前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6}
‘1’ 是當前 前序和中序 的根節點;
根據‘1’劃分中序為{4,7,2} 和 {5,3,8,6}
根據中序序列的劃分,再劃分前序 序列為{2,4,7}和{3,5,6,8}
那么得到的前序{2,4,7}和中序{4,7,2} 就是左子樹的兩個序列;前序{3,5,6,8}和中序{5,3,6,8}就是右子樹的兩個序列
再分別對左右子樹進行遞歸構建。
注意點:就是下標問題,這個地方需要仔細考慮下起止和結束。
對于前序序列是由中序序列的劃分數目得來的,那么左子樹的前序序列 的 結束下標需要減去之前劃分出去的。
這個地方筆者也論述不清,建議以 前序{3,5,6,8}和中序{5,3,6,8} 當右子樹時候來思考這個地方的下標。
特別注意,起始下標不是0,而是前一輪給定的 前序序列開始 和中序序列開始。
題解
// 二叉樹結構
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if (pre != null && in!= null) { // 習慣性防止出現 null傳入
TreeNode treeNode = reConstructBinaryTree(pre, in, 0, pre.length - 1, 0, in.length - 1);
return treeNode;
}
return null;
}
private TreeNode reConstructBinaryTree(int[] pre, int[] in, int preS, int preE, int inS, int inE) {
if (preS > preE || inS > inE ) return null;
TreeNode root = new TreeNode(pre[preS]);
for (int i = inS; i <= inE; i++) {
if (in[i] == pre[preS]){
// 當時寫的時候就考慮下標了,實際上 長度來理解更方便
// 這個 i-inS 就是中序中 根節點的左側結點數量
root.left = reConstructBinaryTree(pre,in,preS+1,preS+i-inS,inS,i-1);
root.right = reConstructBinaryTree(pre,in,preS+i+1-inS,preE,i+1,inE);
break;
}
}
return root;
}