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