给定两个整数数组
preorder
和inorder
,其中preorder
是二叉树的先序遍历,inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
解法1 暴力解法
思路
前序遍历的第一个节点是根节点,而根据根节点的值,再到中序遍历中寻找根节点,而这根节点左边则是左子树,右边则是右子树。递归处理即可。
代码
function buildTree(preorder: number[], inorder: number[]): TreeNode | null {
if (preorder.length === 0 || inorder.length === 0) {
return null;
}
// 第一个是根节点
const rootVal = preorder[0];
const root = new TreeNode(rootVal);
// 在中序遍历中找这个值的位置
const midIndex = inorder.indexOf(rootVal);
// 递归构建左子树和右子树
root.left = buildTree(preorder.slice(1, 1 + midIndex), inorder.slice(0, midIndex));
root.right = buildTree(preorder.slice(1 + midIndex), inorder.slice(midIndex + 1));
return root;
};
时空复杂度
主要是 slice
复制数组的时空开销
时间复杂度:O(n^2)
空间复杂度:O(n^2)
解法2 map优化索引
思路
这个方法就是对于上面暴力解法的优化,通过哈希表来存储中序遍历的索引。具体执行逻辑其实没有区别。
代码
function buildTree(preorder: number[], inorder: number[]): TreeNode | null {
const indexMap = new Map();
for (let i = 0; i < inorder.length; i++) {
indexMap.set(inorder[i], i);
}
let preIndex = 0;
const helper = (left, right) => {
if (left > right) return null;
const rootVal = preorder[preIndex++];
const root = new TreeNode(rootVal);
const index = indexMap.get(rootVal);
root.left = helper(left, index - 1);
root.right = helper(index + 1, right);
return root;
}
return helper(0, inorder.length - 1);
};
时空复杂度
时间复杂度:O(n)
空间复杂度:O(n)