说明:
以先序遍历和中序遍历为例。因为先序和后续遍历是反过来的,所以处理类似。至于使用先序和后序遍历重构,有待发现咯▲嘻嘻▲
题目
给定一个二叉树的先序遍历顺序和一个中序遍历顺序(一种遍历中不含存在重复数据),希望你能重构该二叉树?
构建节点的数据结构:
class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}例:
先序遍历:preorder = [1,2,3,4,5,6,7,8,9]
中序遍历:inorder = [4,3,2,5,1,7,6,8,9]

思路
若能直接按照先序遍历或者中序顺序重构二叉树无疑是最好的选择。
若选用先序遍历建立二叉树,我们遇到的问题是,该何时从构建左子树的过程中结束(我们称该节点为一个结束点)?
如:使用先序遍历1,2,3,4到了4的时候我们就应该结束当前子树的构建(第一个结束点)。
此时发现4这个结束点在中序遍历中刚好是第一个出现的,此时也是我们遍历时出现的第一个结束点。
检查正确的先序遍历过程中其他结束点我们发现:
先序遍历中结束点出现的顺序就是中序遍历的顺序,那么我们可以从先序遍历构建二叉树的过程中改进一下,增加一个判断当前是否是结束点的条件(即当前遍历节点的值是否与中序遍历中的值相同),若当前点是结束点,则结束当前子树的遍历。
程序
class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class BuildTree {
private int nowPreIndex;
private int nowInIndex;
private int preLength;
int [] preorder,inorder;
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder==null||inorder==null)
return null;
nowPreIndex = nowInIndex =0;
this.preLength = preorder.length;
this.preorder = preorder;
this.inorder = inorder;
//函数递归顺序同先序遍历,此时函数执行从最内层到的顺序与inorder中的顺序相同
return buildTree2(Integer.MAX_VALUE);
}
private TreeNode buildTree2(int inStop){
if(nowPreIndex>=preLength) //到达先序遍历最后一个元素
return null;
if(inorder[nowInIndex] == inStop){ //中序遍历和先序遍历相遇则为真,左子树完毕,返回上一层
++ nowInIndex; //中序遍历下一个
return null;
}
TreeNode node = new TreeNode(preorder[nowPreIndex++]); //
node.left = buildTree2(node.val); //构造左子树
node.right = buildTree2(inStop); //构造右子树
return node;
}
}
版权声明:本文为En_Huan原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。