同剑指offer 07 - 重建二叉树/LCR 124
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
题解
分治算法模版
//终止条件:左边界越过右边界
if(left>right) break;
//根据题目条件找到pivot
//划分数组为(left,pivot-1)和(pivot+1,right)
//如果是二叉树,则有root.left=dfs(nums,left,pivot-1),root.right=dfs(pivot+1,right)
//继续找左右数组的pivot,继续划分左右数组直至终止
分治算法解析:
一、当前需做的步骤:
1.前序遍历的第一个节点为根节点
2.分治中序数组:在中序遍历中搜索根节点 的索引,将中序遍历结果划分为 [ 左子树 | 根节点 | 右子树 ] ,由此得到左右子树数目
3.分治前序数组:根据左右子树数目去将前序遍历划分为[ 根节点 | 左子树 | 右子树 ] 。
二、继续分治:
1.根据前序的性质,可以得到左子树的根节点和右子树的根节点
可以继续通过划分中序序列划分左右子树,将左右子树继续化划分下去,即root.left=dfs(前序序列,前序左子树左边界,前序左子树右边界,中序序列,中序左子树左边界,中序左子树右边界)
三、返回条件
前序遍历左边界越过右边界||中序遍历左边界越过右边界
为了提升效率,本文使用哈希表 dic 存储中序遍历的值与索引的映射,查找操作的时间复杂度为 O(1) ;
代码实现
//递归+分治
/*
一、当前需做的步骤:
1.前序遍历的第一个节点为根节点
2.分治中序数组:通过根节点将中序遍历结果划分为左中右,由此得到左右子树数目
3.分治前序数组:根据左右子树数目去将前序遍历划分为中左右
二、继续分治:
1.根据前序的性质,可以得到左子树的根节点和右子树的根节点(可以继续通过划分中序序列划分左右子树),将左右子树继续化划分下去,即root.left=dfs(前序序列,前序左子树左边界,前序左子树右边界,中序序列,中序左子树左边界,中序左子树右边界)
三、返回条件
前序遍历左边界越过右边界||中序遍历左边界越过右边界
*/
class Solution {
HashMap<Integer,Integer> map = new HashMap<>();
public TreeNode deduceTree(int[] preorder, int[] inorder) {
//将中序遍历的值及索引放在map中,避免后续需要遍历中序数组寻找root的下标值,将找root下标这一步骤时间复杂度由O(n)变为O(1)
for(int i=0;i<inorder.length;i++){
map.put(inorder[i],i);
}
return recur(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
}
//记住这里左闭右闭
//需要两个遍历序列的左右边界值是因为需要对两个遍历序列都进行分治
public TreeNode recur(int[] preorder,int preLeft,int preRight,int[] inorder,int inLeft,int inRight){
//终止条件:分治前序数组或中序数组时左边界越过右边界
if(preLeft>preRight||inLeft>inRight) return null;
//获得根节点
TreeNode root = new TreeNode(0);
root.val=preorder[preLeft];
//通过根节点将中序遍历结果划分为左中右,由此得到左右子树数目
//这里用查找map替代了遍历中序数组查找root节点的下标
//mid:根节点的index
int mid = map.get(preorder[preLeft]);
//分别分治前序数组和中序数组
/*
1.中序数组分治为(inLeft,mid-1)和(mid+1,inRight)
2.可得出左子树长度为(mid-inLeft),右子树长度为(inRight-mid-2)
3.前序数组分治为(preLeft+1,preLeft+mid-inLeft)和(preLeft+mid-inLeft+1,preRight)
*/
root.left=recur(preorder,preLeft+1,preLeft+mid-inLeft,inorder,inLeft,mid-1);
root.right=recur(preorder,preLeft+mid-inLeft+1,preRight,inorder,mid+1,inRight);
//返回值
return root;
}
}