剑指offer:重建二叉树
题意描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解题思路
一、递归
- 根据二叉树的前序遍历与中序遍历,可以看出二叉树的根节点是1。
- 根据中序遍历,根节点的左边是左子树{4,7,2},根节点的右边是右子树{5,3,8,6}。
- 我们可以向下递归
- 左子树先序遍历{2,4,7},中序遍历{4,7,2}。可以发现,左子树以2为根,2的左子树为{4,7},无右子树
- 右子树先序遍历{3,5,6,8},中序遍历{5,3,8,6}.可以发现,左子树以3为根,3的左子树为{5},右子树为
- 继续向下递归
- 先序遍历{4,7},中序遍历{4,7},可以发现,2是4的左子树,7是4的右子树
- 先序遍历{6,8},中序遍历{8,6},可以发现,6是3的右子树,8是6的左子树
public class Solution {
public TreeNode reConstructBinaryTree(int[] pre,int[] in) {
TreeNode root = BinaryTree(pre,0,pre.length-1,in,0,in.length-1);
return root;
}
private TreeNode BinaryTree(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]){ //确定中序遍历中根节点的位置
//左子树
//前序遍历【startPre+1,startPre+i-startIn】
//(i-startIn)是左子树的长度
//中序遍历【startIn,i-1】
root.left=BinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
//右子树
//前序遍历【startPre+i-startPre+1,endPre】
//startPre+(i-startPre)+1 确定右子树的起始位置
//中序遍历【i+1,endIn】
root.right=BinaryTree(pre,startPre+i-startIn+1,endPre,in,i+1,endIn);
break;
}
}
return root;
}
}
二、非递归
- 使用前序遍历的第一个元素创建根节点。
- 创建一个栈,将根节点压入栈内。
- 初始化中序遍历下标为 0。
- 遍历前序遍历的每个元素,判断其上一个元素(即栈顶元素)是否等于中序遍历下标index指向的元素。
- 若栈顶元素不等于中序遍历下标index指向的元素,则将当前元素作为其栈顶元素的左子节点,并将当前元素压入栈内。
- 若栈顶元素等于中序遍历下标index指向的元素,则从栈内弹出栈顶元素,同时令中序遍历下标index指向下一元素,之后继续判断栈顶元素是否等于中序遍历下标指向的元素,若相等则重复该操作,直至栈为空或者元素不相等。然后令当前元素为最后一个相等元素的右节点。
- 遍历结束,返回根节点。
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
TreeNode root = new TreeNode(pre[0]);
int len = pre.length;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
int index = 0; //记录中序节点下标
for(int i=1;i<len;i++){
int preVal = pre[i]; //记录前序遍历当前元素
TreeNode node = stack.peek();
if(node.val != in[index]){ //栈顶元素 != 中序遍历元素
node.left = new TreeNode(preVal); //栈顶元素的左子节点 = 当前元素
stack.push(node.left); //入栈
}else{
//栈顶元素 = 中序遍历元素
while(!stack.isEmpty() && stack.peek().val == in[index]){
node = stack.pop(); //弹出栈顶元素
index ++; //更新中序节点下标
}
node.right = new TreeNode(preVal); //最后一个相等元素的右节点 = 当前节点
stack.push(node.right); //入栈
}
}
return root;
}
}

浙公网安备 33010602011771号