一、根据先序和中序遍历结果,还原二叉树。如给定先序访问结果[3, 9, 20, 15, 7]和中序访问结果[9, 3, 15, 20, 7],还原出二叉树如下.
分析:先序访问的第一个元素必然是root节点,而中序访问时,root元素是左子树和右子树的分界点,同时,先序也是先访问左子树再访问右子树。因此,可以根据先序结果知道root,然后可以根据root节点把中序的结果分成左子树和右子树,再根据左子树元素个数和右子树元素个数,把先序结果也分成左子树和右子树。依次递归,即可得到结果。
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder.length == 0)
return null;
TreeNode root = new TreeNode(preorder[0]);
if(preorder.length == 1) //叶子
return root;
int i;
for(i = 0; i < preorder.length; i++){ //寻找中序的分界点
if(inorder[i] == preorder[0]) break;
}
root.left = buildTree(Arrays.copyOfRange(preorder, 1, i + 1), Arrays.copyOfRange(inorder, 0, i));
root.right = buildTree(Arrays.copyOfRange(preorder, i + 1, preorder.length), Arrays.copyOfRange(inorder, i + 1, inorder.length));
return root;
}
二、根据中序和后续访问结果,还原二叉树,同样的思路。
public TreeNode buildTree(int[] inorder , int[] postorder) {
if(postorder.length == 0)
return null;
return build(0, postorder.length - 1, 0, inorder.length - 1, postorder, inorder);
}
public TreeNode build(int pl, int ph, int il, int ih, int[] postorder, int[] inorder){
if(pl > ph || il > ih) //需判断,并返回null,否则如果节点的右儿子为空时的会出错
return null;
TreeNode root = new TreeNode(postorder[ph]);
if(ph == pl)
return root;
int i;
for(i = ih; i > il; i--){
if(inorder[i] == postorder[ph]) break;
}
root.left = build(pl, pl + i - il - 1, il, i - 1, postorder, inorder); //注意postorder数组的边界,不能直接以i为参照,而应以postorder的下边界加上子数组的长度,否则当inorder中间有root节点时会出错
root.right = build(pl + i - il, ph - 1, i + 1, ih, postorder, inorder);
return root;
}