参考文章:
https://www.cnblogs.com/wuguanglin/p/reConstructBinaryTree.html
https://wenhuiyang-luck.github.io/2017/07/24/《剑指offer》— JavaScript(4)重建二叉树/
https://www.jianshu.com/p/ecf61a11f412
https://blog.csdn.net/sinat_36521655/article/details/80592555
https://www.cnblogs.com/echovic/p/6430638.html
1.题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
二叉树是每个节点最多有两个子树的树结构。
前序遍历:首先访问根,再先序遍历左子树,最后先序遍历右子树。
中序遍历:首先中序遍历左子树,再访问根,最后中序遍历右子树。
后序遍历:首先后序遍历左子树,再后序遍历右子树,最后访问根。
2.解题思路
1.二叉树的前序遍历和中序遍历中确定根节点位置。
2.假设有n个节点,在中序遍历左侧的值是左子树的节点,假设共有m个,右侧的值是右子树的节点,则右子树节点为n-m-1个。
3.在前序遍历中,根节点紧挨着的m个节点就是左子树节点,剩下n-m-1个节点就是右子树节点。
这样递归就可以分别计算出各自的左子树和右子树。
3.代码
先看一版容易理解的:
function reConstructBinaryTree(pre,vin){ //前序遍历pre,中序遍历vin
var idx = vin.indexOf(pre[0]); //通过pre获取根节点,然后通过vin.indexOf获取vin中根节点索引位置
var vinleft = vin.slice(0,idx); //中序左子树
var vinright = vin.slice(idx+1); //中序右子树
var preleft = pre.slice(1,idx+1); //前序左子树
var preright = pre.slice(idx+1); //前序右子树
//递归获取左节点和右节点
return {
var:pre[0];
left:reConstructBinaryTree(preleft,vinleft),
right:reConstructBinaryTree(preright,vinright)
}
}
再看一版:
/* function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
} */
function reConstructBinaryTree(pre, vin)
{
// write code here
if (!pre || pre.length === 0) {
return;
}
var treeNode = {
val: pre[0]
}
for(var i = 0; i < pre.length; i++) {
if (vin[i] === pre[0]) { //循环到中序遍历中的根节点
treeNode.left = reConstructBinaryTree(pre.slice(1, i+1), vin.slice(0, i));
treeNode.right = reConstructBinaryTree(pre.slice(i+1),vin.slice(i+1));
}
}
return treeNode;
console.log(treeNode)
}