题目
给出某二叉树的前序遍历和中序遍历的结果数组,重建二叉树。假设输入的前序遍历和中序遍历中没有重复的数字。
例如:给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:[3,9,20,null,null,15,7]
与LeetCode 105 题重复:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal
算法思路
在遇到二叉树相关问题,多数都会利用递归或回溯来解题,本题也是如此。
题目分析:
- 前序遍历的特点:【根节点 | 左子树 | 右子树】,以题目实例为例:【3 | 9 | 20 15 7】
- 中序遍历的特点:【左子树 | 根节点 | 右子树】,以题目示例为例:【9 | 3 | 15 20 7】
- 题目红中还给出了不包含重复的数字,表明树中每个节点都是唯一的。
所以,根据以上信息我们可以进行以下工作:
- 1、首先前序遍历的首元素即为该树的根节点root的值,此时我们只知道根节点,而不知道根节点的左子树和右子树,需要通过后两步分析得到;
- 2、然后在中序遍历中搜索根节点root的索引,可以将中序遍历分为【左子树 | 根节点 | 右子树】;
-3、然后再根据中序遍历的左/右子树节点数量,将前序遍历分为【根节点 | 左子树 | 右子树】 - 4、至此,第一层结束,继续递归前序遍历中的左/右子树,重复步骤1,依次类推。
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
//pre 用于存放前序遍历的结果,作为全局变量,不用在递归时作为参数传递
int[] pre;
//map用于存放中序遍历的数字及其索引,以便于通过前序的根节点找到在中序遍历中的索引
Map<Integer,Integer> map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
int n = preorder.length;
for(int i = 0;i < n;i++) map.put(inorder[i],i);//将中序的值为键,索引为值存入map集合
pre = preorder;
TreeNode res = findtree(0,0,n-1);//递归调用
return res;
}
/**
* @param preroot 先序遍历的索引 当前树的根节点
* @param left 中序遍历的索引 当前树的左边界
* @param right 中序遍历的索引 当前树的右边界
*/
public TreeNode findtree(int preroot,int left,int right){
if(left > right) return null;//当left大于right时,说明当前root没有子节点
TreeNode root = new TreeNode(pre[preroot]); //以先序遍历的索引处的值作为根节点
int i = map.get(pre[preroot]);//得到根节点在中序遍历中的索引
root.left = findtree(preroot+1,left,i-1);//递归根节点的左子树,在前序遍历中,preroot = preroot+1,left不变,right为根节点的索引减1
root.right = findtree(preroot + i -left +1,i+1,right);//递归根节点的右子树,preroot为根节点在前序遍历的索引加上左子树的长度(根节点在中序遍历的索引减去左边界left)再加1
return root;
}
}
复杂度
时间复杂度:O(N),前序和中序遍历都只遍历了一次
空间复杂度:O(N),引入了map
975

被折叠的 条评论
为什么被折叠?



