题目:
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
示例:
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
思路:
前序遍历:根 左 右
中序遍历:左 根 右
后序遍历:左 右 根
根据遍历根的顺序去确定哪种排序,现在我们有中序和前序的结果。
preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
很显然,3是根,而9是左子树,前序中9后面的是右子树
我们根据这个特点来确定构建二叉树
具体看代码及注释
复杂度:
时间复杂度:遍历O(n)
空间复杂度:递归最差是O(n),一般为树高
代码:
public class Solution {
//要保留前序遍历的结果,去划分中序遍历
private int pre[];
//用hashmap来保存根在前序中的位置
HashMap<Integer,Integer> map = new HashMap<>();
public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
this.pre = pre;
//进行遍历,将中序遍历中的元素和前序关联起来
for(int i =0;i<vin.length;++i){
map.put(vin[i],i);
}
//调用回溯方法
return recur(0,0,vin.length-1);
}
//root是前序中根的坐标,left,right是中序的左边界和右边界
//总体划分思路就是根据前序中根元素的位置确定中序中根元素的位置再去划分左右子树
private TreeNode recur(int root,int left,int right){
//确定回溯返回条件
if(left>right) return null;
//将根添加到二叉树
TreeNode node = new TreeNode(pre[root]);
//回溯左子树和右子树
//很显然看左边的例子,左子树的根就是前序中原来根的位置往后推一格
//左边界不用变,还是原先的,右边界要改成中序中根的位置减一
//通过我们之前存的map取到
node.left = recur(root+1,left,map.get(pre[root])-1);
//右子树同理 根位置是前序中右子树的起点位置,
//加上左子树的长度即可,左子树长度:map.get(pre[root])-left
node.right = recur(root+map.get(pre[root])-left+1,map.get(pre[root])+1,right);
return node;
}
}