题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解题思路:
假如已知先序序列为ABDECF,中序序列为DBEAFC,如何求解后序序列?由于先序遍历树的规则为根左右,因此可以得出先序序列的第一个元素一定为根节点,即A就是根节点。再看中序序列规则为左根右,再根据结点A的位置,可判断在中序序列中,A的左边的元素即DBE为左子树包含的元素,A的右边的元素FC为右子树中的元素。
其次,递归求解左子树(左子树先序为BDE,中序为DBE),递归求解右子树(右子树先序为CF ,中序为FC)。如此递归到没有左右子树为止。
总结解题步骤:
1.确定树的根节点。树根是当前树中所有元素在先序遍历中最先出现的元素,即先序遍历的第一个结点即为根节点。
2.求解树的子树。找到根在中序遍历序列中的位置。位置左边的结点为左子树,位置右边的结点为右子树。如果根节点的左边或者右边为空,那么该方向子树为空;如果根节点边和右边都为空,那么根节点已经为叶子结点。
3.对二叉树的左右孩子分别进行步骤1、2,直至求出整个二叉树结构位置。
具体实现代码:
public TreeNode buildTree(int[] preorder, int[] inorder) {
TreeNode root = reBuild(preorder,inorder,0,preorder.length - 1,0,inorder.length -1 );
return root;
}
public TreeNode reBuild(int[] preorder,int[] inorder,int preStart,int preEnd,
int inStart,int inEnd) {
if(preStart > preEnd || inStart > inEnd) {
return null;
}
int rootData = preorder[preStart];
TreeNode root = new TreeNode(rootData);
int index = findIndex(inorder,inStart,inEnd,rootData);
//左子树结点个数
int leftNum = index - inStart;
root.left = reBuild(preorder, inorder, preStart+1, preStart+leftNum, inStart, index - 1);
root.right = reBuild(preorder, inorder, preStart+1+leftNum, preEnd, index+1, inEnd);
return root;
}
public int findIndex(int[] inorder,int inStart,int inEnd,int rootData) {
for(int i = inStart;i <= inEnd;i++) {
if(inorder[i] == rootData) {
return i;
}
}
return -1;
}
由中序遍历和后序遍历,重建二叉树类似于上例,直接上代码:
public TreeNode buildTree(int[] inorder, int[] postorder) {
return reBuild(inorder,postorder,0,inorder.length - 1,0,postorder.length - 1);
}
public TreeNode reBuild(int[] inorder, int[] postorder, int inStart,
int inEnd, int postStart, int postEnd) {
if(inStart > inEnd || postStart > postEnd) {
return null;
}
int rootData = postorder[postEnd];
//根节点
TreeNode root = new TreeNode(rootData);
//获取根节点在中序遍历中的位置
int index = findIndex(inorder,inStart,inEnd,rootData);
int leftNum = index - inStart;
root.left = reBuild(inorder, postorder, inStart, index-1, postStart, postStart+leftNum-1);
root.right = reBuild(inorder, postorder, index+1, inEnd, postStart+leftNum, postEnd -1 );
return root;
}
public int findIndex(int[] inorder,int inStart,int inEnd,int rootData) {
for(int i = inStart;i<= inEnd;i++) {
if(rootData == inorder[i]) {
return i;
}
}
return -1;
}