题目描述
解题思路:递归
前序遍历:根节点->左子节点->右子节点
中序遍历:左子节点->根节点->右子节点
针对前序和中序遍历的特点,我们不难得出以下思路
在每一轮递归中:
1、用preorder的头部值 初始化当前的root节点
2、在传入的2个数组的基础上,划分出当前root的左子树的前序/中序遍历数组、以及右子树的前序/中序遍历数组
3、调用自身,将左子树和右子树挂载到当前root上
4、返回当前root
下面我们具体来看第2个步骤如何实现
我们可以利用js提供的 indexOf 数组方法,找出当前root在inorder数组中的位置(记为 rootIndex)
因此,在inorder数组中,左子树和右子树的inorder数组分别位于 rootIndex 的左边和右边
这样一来,我们就可以利用 js 提供的 slice 方法,在原数组的基础上进行切割,从而得到左右子树的前序/中序遍历数组
除此之外,我们还要考虑一些特殊的情况:
- 传入的前序/中序遍历数组为空:返回空
- 传入的前序/中序遍历数组长度为1:当前为叶子节点
- rootIndex 等于 0 :当前root节点没有左子树
- rootIndex + 1 等于 数组的长度 :当前 root节点没有右子树
代码实现(Javascript)
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {number[]} preorder
* @param {number[]} inorder
* @return {TreeNode}
*/
var buildTree = function(preorder, inorder) {
if(preorder.length===0 || inorder.length===0){
return null
}
if(preorder.length === 1 && inorder.length === 1){//没有左右子树
return new TreeNode(preorder[0])
}
var root=new TreeNode(preorder[0])
let rootIndex=inorder.indexOf(root.val)
if(rootIndex!==0){ // 有左子树
var leftinorder=inorder.slice(0,rootIndex)
if(rootIndex + 1 >= preorder.length){//有左子树,没有右子树
var leftpreorder=preorder.slice(1)
root.left = buildTree(leftpreorder, leftinorder)
root.right= buildTree([],[])
}else{ // 有左右子树
var leftpreorder=preorder.slice(1,rootIndex+1)
var rightinorder=inorder.slice(rootIndex+1)
var rightpreorder=preorder.slice(rootIndex+1)
root.left = buildTree(leftpreorder, leftinorder)
root.right = buildTree(rightpreorder, rightinorder)
}
}else{ // 没有左子树
var rightinorder=inorder.slice(rootIndex+1)
var rightpreorder=preorder.slice(rootIndex+1)
root.left = buildTree([],[])
root.right = buildTree(rightpreorder, rightinorder)
}
return root
};