題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。
假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。
解析:
①首先根據前序遍歷可知,前序序列的第一個元素爲根節點,即1爲根節點;
②在中序遍歷序列中找到1所在的位置,1之前的序列爲左子樹,即{4,7,2}爲根節點的左子樹。1之後的序列爲右子樹,即{5,3,8,6}爲根節點的右子樹;
③左子樹{4,7,2}對應前序遍歷中的[2,4,7},所以2爲根節點,右子樹{5,3,8,6}對應前序遍歷中的{3,5,6,8},所以5爲根節點;
④重複②③步驟,即進入遞歸求解。
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if (pre == null || in == null) return null;
TreeNode root = null;
root = rebuild (pre,0,pre.length-1,in,0,in.length-1);//重建二叉樹
return root;
}
//核心遞歸函數
public TreeNode rebuild(int[] pre, int startpre, int endpre, int[] in, int startin, int endin){
if (startpre > endpre || startin > endin) return null;//遞歸結束條件
TreeNode root = new TreeNode(pre[startpre]);//前序遍歷序列中第一個元素爲根節點
for (int i = startin; i <= endin; i++){
if (in[i] == pre[startpre]){//pre[startpre]爲根,找出其對應在中序遍歷in中的根元素
//對根節點的左子樹進行遞歸操作,注意此時根節點的位置
root.left = rebuild(pre,startpre+1,startpre+i-startin,in,startin,i-1);
//對根節點的右子樹進行遞歸操作
root.right = rebuild(pre,startpre+i-startin+1,endpre,in,i+1,endin);
}
}
return root;
}
拓展:中序 後序遍歷構造二叉樹
操作跟上面一樣
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (inorder == null || postorder == null) return null;
TreeNode root = null;
root = buildTree(inorder,0,inorder.length-1,postorder,0,postorder.length-1);
return root;
}
public TreeNode buildTree(int[] inorder,int startin,int endin,int[] postorder,int startpost,int endpost){
if (startin > endin || startpost > endpost) return null;
TreeNode node = new TreeNode(postorder[endpost]);
for (int i = startin; i <= endin;i++){
if (inorder[startin] == postorder[endpost]){
node.left = buildTree(inorder,startin,i-1,postorder,startpost,i-startin-1+startpost);
node.right = buildTree(inorder,i+1,endin,postorder,i-startin+startpost,endpost-1);
}
}
return node;
}