重建二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素
示例:
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/
9 20
/
15 7
递归方式:
- 设置递归函数
build
,参数x
,y
表示当前子树所在inOrder
数组区间 - 递归退出条件:
x > y
- 当前子树根结点的值设为前序遍历的队头(按照)
- 获取根结点对应中序遍历的位置
index
- 递归调用建立左右子树,左子树区间
[x,index-1]
,右子树区间[index+1,y]
- 返回根结点
var buildTree = function (preorder, inorder) {
function build(x, y) {
if (x > y) return null;
//结点的值
let val = preorder.shift();
//创建根节点
let rt = new TreeNode(val);
//获取中序遍历的索引
let index = inorder.indexOf(val);
//建立左右子树
rt.left = build(x, index - 1);
rt.right = build(index + 1, y);
return rt;
}
return build(0, inorder.length - 1);
};
非递归方式:
- 利用栈先进后出的规律,按照先右后左的顺序进栈,可以实现左子树所有元素的优先访问,弹出顺序为前序遍历的顺序,取结点时即可按照preoreder数组的顺序赋值
- 根据结点的值获得当前结点node在中序遍历的索引index
- 通过判断[node.x,index-1],[index+1,node.y]区间是否合法来确定是否创建左右子树
var buildTree = function (preorder, inorder) {
if (!inorder.length) return null;
let root = new TreeNode();
root.x = 0, root.y = inorder.length - 1;
let stack = [root];
while (stack.length) {
//获取根结点
let node = stack.pop();
node.val = preorder.shift();
//找到中序遍历索引
let index = inorder.indexOf(node.val);
//创建右子树
if (index + 1 <= node.y) {
node.right = new TreeNode();
node.right.x = index + 1;
node.right.y = node.y;
stack.push(node.right);
}
//创建左子树
if (node.x <= index - 1) {
node.left = new TreeNode();
node.left.x = node.x;
node.left.y = index - 1;
stack.push(node.left);
}
}
return root;
};