1 题目
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
限制:
0 <= 节点个数 <= 5000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2 Java
先贴个例子:
以中序序列为核心,这一段序列中,1为根节点(由前序序列preorder[0]得到),1左侧为1左子树的所有节点,1右侧是1右子树的所有节点。
由此可以推出递归的子问题大致形式:
任意子问题皆有两段相对应的前序、中序序列,preorder[0]将中序序列分割为左子树所有节点、根节点、右子树所有节点三部分,左右子树又是两个子问题。
问题的难点在于,如何确定子问题中两段序列的范围,尤其是前序序列
注:prEnd的值也需要求,因为右子树子问题的prStart是由父问题的prEnd求出
4 三刷
4.1 方法一(分治递归)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
Map<Integer, Integer> map = new HashMap<>();
int[] pre;
public TreeNode buildTree(int[] preorder, int[] inorder) {
pre = preorder;
// 创建map逆向数组
for(int i = 0; i < inorder.length; i++){
map.put(inorder[i], i);
}
return helper(0, 0, inorder.length - 1);
}
public TreeNode helper(int p, int l, int r){
if(l > r) return null;
// 逆向数组,获取inorder中该根节点的索引
int index = map.get(pre[p]);
// 创建该根节点,左子树,右子树
TreeNode root = new TreeNode(pre[p]);
root.left = helper(p + 1, l, index - 1);
root.right = helper(p + index - l + 1, index + 1, r);
return root;
}
}
4.2 方法二(略微改进写法,方便理解先分后治)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
Map<Integer, Integer> map = new HashMap<>();
int[] pre;
public TreeNode buildTree(int[] preorder, int[] inorder) {
pre = preorder;
// 创建map逆向数组
for(int i = 0; i < inorder.length; i++){
map.put(inorder[i], i);
}
return helper(0, 0, inorder.length - 1);
}
public TreeNode helper(int p, int l, int r){
if(l > r) return null;
// 先分
// 逆向数组,获取inorder中该根节点的索引
int index = map.get(pre[p]);
TreeNode left = helper(p + 1, l, index - 1);
TreeNode right = helper(p + index - l + 1, index + 1, r);
// 后治
TreeNode root = new TreeNode(pre[p]);
root.left = left;
root.right = right;
return root;
}
}