题目:
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
思路:
给了我们两个数组,一个是前序遍历的结果, 一个是中序遍历的结果
画个图更加直观的表达
(图片来自labuladong)
根据两种遍历结果的特点可知, preorder前序遍历数组的第一个元素是根节点,而在中序遍历数组中根节点在数组中间,两边是左右子树的数组
我们可以利用两个数组的特性来构建整棵二叉树
先从preorder中取第一个元素,也就是当前根节点的值,索引是preStart,值是preorder[preStart]
题目说值不重复,我们可以先把inorder的值和索引存在哈希表中,方便根据根节点的值获取在中序遍历数组中根节点的索引
我们根据root的值获取到根节点在中序遍历数组的值后, 就可以计算出当前根节点的左右子树的数组的长度了
知道子树的长度了,我们就可以在前序遍历数组中切割出左右子树
然后递归构造root节点的左右子树
将分割的子树前序数组的第一个元素构建子树的根节点 ......重复
代码:
var buildTree = function (preorder, inorder) {
//创建map
let valToIndex = new Map();
//提前遍历中序数组
for (let i = 0; i < inorder.length ; i++) {
valToIndex.set(inorder[i], i);
}
return build(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
//构建build函数,参数分别为,前序遍历数组,数组开始索引,结束索引,中序遍历数组,开始索引,结束索引
function build(preorder, preStart, preEnd, inorder, inStart, inEnd) {
//出口base case
if (preStart > preEnd) return null;
// if (inStart > inEnd) return null;
//找根节点,就是前序遍历数组的第一个元素
let rootVal = preorder[preStart];
//获取根节点在中序遍历数组中的元素索引index
let index = valToIndex.get(rootVal);
//计算左右子数组长度,通过中序遍历数组
let leftLen = index - inStart;
// let rightLen = inEnd - index;
//构造根节点
let root = new TreeNode(rootVal);
//递归构建左右子树
root.left = build(preorder, preStart + 1, preStart + leftLen, inorder, inStart, index - 1);
root.right = build(preorder, preStart + leftLen + 1, preEnd, inorder, index + 1, inEnd);
//返回当前节点
return root;
}
};