495 字
2 分钟
从前序与中序遍历序列构造二叉树

题目描述
给定两个整数数组 preorder
和 inorder
,其中 preorder
是二叉树的先序遍历, inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
解题思路
- 根节点定位:
- 前序序列首元素为当前子树根节点
- 在中序序列中定位根节点位置
- 子树划分:
- 中序序列中,根节点左侧为左子树节点
- 根节点右侧为右子树节点
- 递归构建:
- 根据子树节点数量划分前序序列
- 递归构建左子树和右子树
- 终止条件:
- 序列为空时返回 null
- 单节点时直接返回叶子节点
关键洞察
- 序列特性利用:
- 前序序列:
[根, [左子树], [右子树]]
- 中序序列:
[[左子树], 根, [右子树]]
- 前序序列:
- 索引映射优化:
- 预处理中序序列值→索引映射
- O(1) 时间定位根节点位置
- 子树尺寸计算:
- 左子树节点数 = 中序根索引 - 中序起始索引
- 据此划分前序序列左右子树部分
- 递归边界处理:
- 严格限定序列区间起止位置
- 区间无效时立即终止递归
复杂度分析
指标 | 说明 |
---|---|
时间复杂度 | O(n):每个节点精确处理一次(哈希表构建O(n),递归构建O(n)) |
空间复杂度 | O(n):哈希表存储O(n) + 递归栈O(h)(h为树高,最坏O(n)) |
代码实现
/** * 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 || !inorder.length) return null; const n = preorder.length; const leftSize = inorder.indexOf(preorder[0]); const pre1 = preorder.slice(1, 1 + leftSize); const pre2 = preorder.slice(1 + leftSize); const in1 = inorder.slice(0, leftSize); const in2 = inorder.slice(1 + leftSize, n); const left = buildTree(pre1, in1); const right = buildTree(pre2, in2); return new TreeNode(preorder[0], left, right)};