【算法训练】LeetCode#105 从前序与中序遍历序列构造二叉树
一、描述
105. 从前序与中序遍历序列构造二叉树
给定两个整数数组 preorder
和 inorder
,其中 preorder
是二叉树的先序遍历, inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
示例 2:
输入: preorder = [-1], inorder = [-1]
输出: [-1]
二、思路
光根据一个遍历序是无法确定唯一树的,所以这道题是根据前和中序构造。初步想法是根据前序的根节点对中序遍历上的节点做划分,能够区分出其余节点在左子树还是右子树,然后对于子树再进行相同操作。(没把握却一次过..)
三、解题
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public static class Solution {
int preLoc = -1;
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder == null || inorder == null || preorder.length < 1 || inorder.length < 1){
return null;
}
return process(preorder,inorder,0,inorder.length-1,findRoot(preorder,inorder,0,inorder.length-1));
}
public TreeNode process(int[] preorder,int[] inorder,int inLeftLoc,int inRightLoc,int root){
if (inLeftLoc > inRightLoc){
return null;
}
if (inLeftLoc == inRightLoc){
// 范围上只有一个节点
return new TreeNode(inorder[inLeftLoc]);
}
TreeNode node = new TreeNode(inorder[root]); // 根节点
node.left = process(preorder,inorder,inLeftLoc,root-1,findRoot(preorder,inorder,inLeftLoc,root-1));
node.right = process(preorder,inorder,root+1,inRightLoc,findRoot(preorder,inorder,root+1,inRightLoc));
return node;
}
// 返回当前先序遍历中的位置就是接下来的根节点(根据先序遍历的特点)
public int findRoot(int[] preorder,int[] inorder,int leftLoc,int rightLoc){
if (leftLoc > rightLoc){
return -1;
}
int val = preorder[++this.preLoc]; // 得到下一个根节点的值
int ans = 0;
for (int i = leftLoc ; i <= rightLoc ; i++){
// 在给定范围上找到中序遍历中根节点位置
if (inorder[i] == val){
ans = i;
break;
}
}
return ans;
}
// 因为节点不重复,所以每次找寻root节点时可以用map进行优化
public TreeNode buildTreeV2(int[] preorder, int[] inorder) {
if (preorder == null || inorder == null || preorder.length < 1 || inorder.length < 1){
return null;
}
int n = preorder.length;
indexMap = new HashMap<Integer, Integer>();
for (int i = 0; i < n; i++) {
indexMap.put(inorder[i], i); // 根据根节点的值知道inorder中根节点位置
}
return process(preorder,inorder,0,inorder.length-1,indexMap.get(preorder[++preLoc]));
}
public TreeNode processV2(int[] preorder,int[] inorder,int inLeftLoc,int inRightLoc,int root){
if (inLeftLoc > inRightLoc){
--preLoc;
return null;
}
if (inLeftLoc == inRightLoc){
// 范围上只有一个节点
return new TreeNode(inorder[inLeftLoc]);
}
TreeNode node = new TreeNode(inorder[root]); // 根节点
node.left = preLoc == indexMap.size()-1 ? null : process(preorder,inorder,inLeftLoc,root-1,indexMap.get(preorder[++preLoc]));
node.right = preLoc == indexMap.size()-1 ? null : process(preorder,inorder,root+1,inRightLoc,indexMap.get(preorder[++preLoc]));
return node;
}
}