本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
题目解析
思路一
我们根据先序遍历和中序遍历创建二叉树,我们先序遍历的第一个节点一定是根节点,在取出当前子树的根节点,在创建一个节点树,在中序遍历的结果中寻找到该节点,并获取根节点在中序遍历的位置,如果没有该节点则该子树创建完毕,在根据根节点左边的结点创建左子树和根据根节点右边的结点创建右节点数,最后依次遍历得到最终的二叉树,返回其根节点
var buildTree = function(preorder, inorder) {
if(!preorder || preorder.length === 0) return null;
if(!inorder || inorder.length === 0) return null;
let node = preorder.shift();
let root = new TreeNode(node);
let index = inorder.indexOf(node);
if(index === -1) return;
let leftInOrder = inorder.slice(0,index);
let rightInOrder = inorder.slice(index+1,inorder.length);
root.left = buildTree(preorder,leftInOrder);
root.right = buildTree(preorder,rightInOrder);
return root;
};
思路二
我们先进行获取树的节点个数,在创建一个哈希表map,用来存储中序遍历的各个节点进行存储节点值和当前下标,在构建一个递归函数,设置如果此时树的左边界大于右边界,则直接退出返回null,不执行下面的操作,在获得此树的根节点下标位置,通过中序遍历的特性获得左子树的节点个数,创建一个树节点,并赋值,在递归左子树和递归右子树并传对应的参数,在返回此时的树,最后调用递归函数,并返回
/**
* @param {number[]} preorder
* @param {number[]} inorder
* @return {TreeNode}
*/
var buildTree = function(preorder, inorder) {
let length = inorder.length;
let map = new Map();
for(let i=0; i<length; i++){
map.set(inorder[i], i);
}
const createTree = (preorderLeft, preorderRight, inorderLeft, inorderRight) => {
if(preorderLeft > preorderRight){
return null;
}
let preorderRoot = preorderLeft;
let inorderRoot = map.get(preorder[preorderRoot]);
let leftTreeNum = inorderRoot - inorderLeft;
let root = new TreeNode(preorder[preorderRoot]);
root.left = createTree(preorderLeft + 1, preorderLeft + leftTreeNum, inorderLeft, inorderRoot - 1);
root.right = createTree(preorderLeft + leftTreeNum + 1, preorderRight, inorderRoot + 1, inorderRight);
return root;
}
return createTree(0, length - 1, 0, length - 1);
};