import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
/**
* NC12 重建二叉树
* @author d3y1
*/
public class Solution {
HashMap<Integer,Integer> inMap = new HashMap<>();
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 相似 -> NC223 从中序与后序遍历序列构造二叉树 [nowcoder]
*
* @param preOrder int整型一维数组
* @param vinOrder int整型一维数组
* @return TreeNode类
*/
public TreeNode reConstructBinaryTree (int[] preOrder, int[] vinOrder) {
// return solution1(preOrder, vinOrder);
// return solution2(preOrder, vinOrder);
return solution3(preOrder, vinOrder);
}
/**
* 递归
* @param preOrder
* @param vinOrder
* @return
*/
private TreeNode solution1(int[] preOrder, int[] vinOrder){
return construct(preOrder, vinOrder);
}
/**
* 递归
* @param preOrder
* @param vinOrder
* @return
*/
public TreeNode construct (int[] preOrder, int[] vinOrder) {
int n = preOrder.length;
if(n == 0){
return null;
}
// 当前根结点
int rootVal = preOrder[0];
TreeNode root = new TreeNode(rootVal);
// 当前根结点 左子树节点个数
int left = 0;
while(vinOrder[left] != rootVal){
left++;
}
if(left > 0){
// int[] pre = new int[left];
// int[] vin = new int[left];
// System.arraycopy(preOrder, 1, pre, 0, left);
// System.arraycopy(vinOrder, 0, vin, 0, left);
// root.left = construct(pre, vin);
root.left = construct(Arrays.copyOfRange(preOrder, 1, left+1), Arrays.copyOfRange(vinOrder, 0, left));
}
// 当前根结点 右子树节点个数
int right = n-(left+1);
if(right > 0){
// int[] pre = new int[right];
// int[] vin = new int[right];
// System.arraycopy(preOrder, left+1, pre, 0, right);
// System.arraycopy(vinOrder, left+1, vin, 0, right);
// root.right = construct(pre, vin);
root.right = construct(Arrays.copyOfRange(preOrder, left+1, n), Arrays.copyOfRange(vinOrder, left+1, n));
}
return root;
}
//////////////////////////////////////////////////////////////////////////////////////
/**
* 哈希 + 递归
* @param preOrder
* @param vinOrder
* @return
*/
private TreeNode solution2(int[] preOrder, int[] vinOrder){
int n = vinOrder.length;
if(n == 0){
return null;
}
// 哈希: val -> idx
for(int i=0; i<n; i++){
inMap.put(vinOrder[i], i);
}
// 根结点
TreeNode root = new TreeNode(preOrder[0]);
// 递归遍历
dfs(preOrder, root, 0, n-1, 0, n-1);
return root;
}
/**
* 递归遍历
* @param preOrder
* @param root
* @param inLeft
* @param inRight
* @param preLeft
* @param preRight
*/
private void dfs(int[] preOrder, TreeNode root, int inLeft, int inRight, int preLeft, int preRight){
int inRootIdx = inMap.get(root.val);
int leftSize = inRootIdx-inLeft;
int rightSize = inRight-inRootIdx;
// 有左子树
if(leftSize > 0){
root.left = new TreeNode(preOrder[preLeft+1]);
dfs(preOrder, root.left, inLeft, inRootIdx-1, preLeft+1, preLeft+leftSize);
}
// 有右子树
if(rightSize > 0){
root.right = new TreeNode(preOrder[preLeft+leftSize+1]);
dfs(preOrder, root.right, inRootIdx+1, inRight, preLeft+leftSize+1, preRight);
}
}
//////////////////////////////////////////////////////////////////////////////////////
// 前序遍历根结点索引
private int preRootIdx;
/**
* 哈希 + 递归
* @param preOrder
* @param vinOrder
* @return
*/
private TreeNode solution3(int[] preOrder, int[] vinOrder){
int n = preOrder.length;
preRootIdx = 0;
// 哈希: val -> idx
for(int i=0; i<n; i++){
inMap.put(vinOrder[i], i);
}
return build(preOrder, 0, n-1);
}
/**
* 递归遍历
*
* 二叉树前序遍历: 根 -> 左 -> 右
* 可利用该性质直接找到前序遍历根节点, 子树遍历先左后右: 左 -> 右
*
* @param preOrder
* @param inLeft
* @param inRight
* @return
*/
private TreeNode build(int[] preOrder, int inLeft, int inRight){
if(inLeft > inRight){
return null;
}
// 根
int preRootVal = preOrder[preRootIdx++];
TreeNode root = new TreeNode(preRootVal);
if(inLeft == inRight){
return root;
}
// 中序遍历根结点索引
int inRootIdx = inMap.get(preRootVal);
// 左
root.left = build(preOrder, inLeft, inRootIdx-1);
// 右
root.right = build(preOrder, inRootIdx+1, inRight);
return root;
}
}