输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
示例 1:
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
示例 2:
Input: preorder = [-1], inorder = [-1]
Output: [-1]
限制:
0 <= 节点个数 <= 5000
递归法
研究一下前序遍历和中序遍历的特点:
前序遍历的第一个节点就是根节点
知道了根节点后,去中序遍历的序列里找,它左边的部分就是它完整的左子树
通过这种方式递归地去区分左子树和右子树,但还需要前序遍历才能知道每个子树中的根节点是哪个
因此需要知道中序遍历和前序遍历中每个子树相对应的是哪一段序列:
大概步骤:
通过前序遍历知道了根节点pre_root的序号,也就知道了根节点的值preorder[pre_root],去中序遍历里找到这个值的位置,也就知道了左子树的节点个数left_size
前序遍历中从pre_left+1到pre_left+left_size的部分,对应中序遍历中左边界in_left到in_left+left_size的部分,也就是左半边
前序遍历中pre_left+1+left_size到右边界pre_right的部分,对应中序遍历中in_root+1到右边界in_right的部分,也就是右半边
分别调用递归函数,递归的终止条件是左边界大于右边界,表示走完了,也就返回null
用什么数据结构?
为了去中序遍历中快速定位root节点,采用hashmap
时间:O(N) N代表树中的节点个数
空间:O(N) 除去返回的答案需要的 O(N) 空间之外,还需要使用 O(N)的空间存储哈希映射,以及 O(h)(其中 h是树的高度)的空间表示递归时栈空间。这里 h < n,所以总空间复杂度为 O(N)。
class Solution {
private Map<Integer,Integer> map;
public TreeNode myBuildTree(int[] preorder,int[] inorder,int pre_left,int pre_right,int in_left,int in_right){//先序的左边界,先序的右边界,中序的左边界,中序的右边界
if(pre_left>pre_right)return null;
int pre_root=pre_left;//前序遍历的第一个就是root
int in_root=map.get(preorder[pre_root]);//找到中序遍历中对应的root位置
int left_size=in_root-in_left;//左子树的节点个数
TreeNode root=new TreeNode(preorder[pre_root]);//建立根节点
root.left=myBuildTree(preorder,inorder,pre_left+1,pre_left+left_size,in_left,in_left+left_size);
root.right=myBuildTree(preorder,inorder,pre_left+left_size+1,pre_right,in_root+1,in_right);
return root;
}
public TreeNode buildTree(int[] preorder, int[] inorder) {
map=new HashMap<Integer,Integer>();
for(int i=0;i<inorder.length;i++){
map.put(inorder[i],i);
}
return myBuildTree(preorder,inorder,0,inorder.length-1,0,inorder.length-1);
}
}
迭代法
暂时没看懂什么意思...感觉两种方法的一个重点都是注意到先序和中序遍历中右子树是最后被访问到的
以后来补这个方法