非独立思考
class Solution {
private static HashMap<Integer, Integer> treeMap = new HashMap<>(16);
public TreeNode buildTree(int[] preorder, int[] inorder) {
// 总体思路:根据先序遍历的根节点,定位到中序遍历的根节点
// 中序遍历的左端点的下标与根节点的下标之差就是左子树的数量,反之是右子树
// 每轮递归中,我们都:
// 1 找到根节点
// 2 按照数量左子树继续递归,作为当前根节点的left
// 3 右子树继续递归,作为当前根节点的right
// 记录中序遍历的k-v映射
for (int i = 0; i < inorder.length; i++) {
treeMap.put(inorder[i], i);
}
TreeNode treeNode = myBuildTree(preorder, inorder,0, preorder.length - 1, 0, inorder.length - 1);
return treeNode;
}
/**
* @param preorder 先序遍历
* @param inorder 中序遍历
* @param preOrderLeft 递归中:先序遍历的左端点
* @param preOrderRight 递归中:先序遍历的右端点
* @param inOrderLeft 递归中:中序遍历的左端点
* @param inOrderRight 递归中:中序遍历的右端点
*/
private TreeNode myBuildTree(int[] preorder, int[] inorder,
int preOrderLeft, int preOrderRight, int inOrderLeft, int inOrderRight) {
// 定义递归结束条件
if (preOrderLeft > preOrderRight) {
return null;
}
// 递归执行流程
// 1 找到先序遍历中的根节点,即preOrderLeft
int preOrderRoot = preOrderLeft;
// 2 据此定位到中序遍历中的根节点
int inOrderRoot = treeMap.get(preorder[preOrderRoot]);
// 3 建立根节点,左递归指向其left,右递归指向其right
TreeNode root = new TreeNode(preorder[preOrderRoot]);
// 建立递归的重要参数是他们的参数变量值为多少
// 根据中序遍历计算左子树个数
int leftSize = inOrderRoot - inOrderLeft;
// 递归构造左子树
// 官方提示:先序遍历中「从 左边界+1 开始的 leftSize」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
root.left = myBuildTree(preorder, inorder, preOrderLeft + 1, preOrderLeft + leftSize, inOrderLeft, inOrderRoot - 1);
// 递归构造右子树
// 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
root.right = myBuildTree(preorder, inorder, preOrderLeft + leftSize + 1, preOrderRight, inOrderRoot + 1, inOrderRight);
// 最后返回root
return root;
}
}
