105. 从前序与中序遍历序列构造二叉树
力扣题目链接[1]
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例1:
代码语言:javascript复制输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
提示:
1 <= preorder.length <= 3000
inorder.length == preorder.length
-3000 <= preorder[i], inorder[i] <= 3000
preorder
和inorder
均 「无重复」 元素inorder
均出现在preorder
preorder
「保证」 为二叉树的前序遍历序列inorder
「保证」 为二叉树的中序遍历序列
思路:
本题考查前序和中序遍历的特点。
- 前序遍历:根左右
- 中序遍历:左根右
我们通过前序遍历可以找到二叉树的根。根据中序遍历,我们可以知道根的左右子树的中序遍历及左右子树节点数目。知道左右子树的节点数目,结合前序遍历,我们就知道左右子树的前序遍历。
然后结合左右子树的前序和中序遍历,递归的构造左右子树为当前构造出节点的左右子树。
代码语言:javascript复制/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {number[]} preorder
* @param {number[]} inorder
* @return {TreeNode}
*/
var buildTree = function(preorder, inorder) {
if (!preorder.length) return null; // 二叉树为空
const root = preorder[0]; // 从前序遍历获取根节点
const node = new TreeNode(root); // 通过根节点构造节点
const index = inorder.indexOf(root); // 从中序遍历获取根节点的索引
const inLeft = inorder.slice(0, index); // 中序遍历的左子树
const inRight = inorder.slice(index 1); // 中序遍历的右子树
const preLeft = preorder.slice(1, index 1); // 前序遍历的左子树
const preRight = preorder.slice(index 1); // 前序遍历的右子树
node.left = buildTree(preLeft, inLeft); // 递归构造左子树
node.right = buildTree(preRight, inRight); // 递归构造右子树
return node; // 返回构造出的节点
};
总结
本题需要结合前序遍历和中序遍历,来将二叉树拆分为左子树、根、右子树三个部分。找出根节点就调用构造函数构造出新节点,左右子树分别有前序遍历和中序遍历两个顺序,然后递归调用函数进而找到左子树的根节点,以及右子树的根节点。这两个根节点恰好就是刚才构造出的新节点的左右子节点,这样便可以递归的构造出一个完整的二叉树。
最终返回根节点即可。
参考资料
[1]
力扣题目链接: https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/