二叉树遍历:
    先序遍历:对任一子树,先访问根,然后遍历其左子树,最后遍历其右子树。
    中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树。
    后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。

    二叉树遍历序列特点:
    前序遍历序列:[根节点,[左子树],[右子树]]
    中序遍历序列:[[左子树],根节点,[右子树]]
    后序遍历序列:[[左子树],[右子树],根节点]

    若要构造二叉树,只要能分别构建出根节点,根节点的左子树,根节点的右子树,那么就能完整地构造出二叉树

    递归算法框架:

    1. public TreeNode buildTree() {
    2. // 找到根节点的值
    3. int rootValue = ?;
    4. // 构建根节点
    5. TreeNode root = new TreeNode(rootValue);
    6. // 构建根节点的左子树
    7. root.left = buildTree();
    8. // 构建根节点的右子树
    9. root.right = buildTree();
    10. return root;
    11. }

    106. 从中序与后序遍历序列构造二叉树 - 图1

    根据题意只要能确定中序遍历序列和后序遍历序列,即可最终构建出一棵二叉树
    只要知道中序遍历序列左侧起始索引和中序遍历序列右侧起始索引即可确定中序遍历序列
    只要知道后序遍历序列左侧起始索引和后序遍历序列右侧起始索引即可确定后序遍历序列

    1. public TreeNode buildTree(int[] inorder, int[] postorder,
    2. int inLeftIndex, int inRightIndex,
    3. int postLeftIndex, int postRightIndex) {
    4. // 找到根节点的值
    5. int rootValue = ?;
    6. // 找到根节点的索引
    7. int rootIndex = ?;
    8. // 构建根节点
    9. TreeNode root = new TreeNode(rootValue);
    10. // 构建左子树
    11. root.left = buildTree(inorder, postorder, ?, ?, ?, ?);
    12. // 构建右子树
    13. root.right = buildTree(inorder, postorder, ?, ?, ?, ?);
    14. return root;
    15. }
    1. public TreeNode buildTree(int[] preorder, int[] inorder) {
    2. HashMap<Integer, Integer> valueIndexMap = new HashMap();
    3. for(int i = 0; i < inorder.length; i++) {
    4. valueIndexMap.put(inorder[i], i);
    5. }
    6. return buildTree(preorder, inorder,
    7. 0, preorder.length - 1,
    8. 0, inorder.length - 1,
    9. valueIndexMap);
    10. }
    11. public TreeNode buildTree(int[] inorder, int[] postorder,
    12. int inLeftIndex, int inRightIndex,
    13. int postLeftIndex, int postRightIndex,
    14. HashMap<Integer, Integer> valueIndexMap) {
    15. if (preLeftIndex > preRightIndex) {
    16. return null;
    17. }
    18. // 找到根节点的值
    19. int rootValue = postorder[postRightIndex];
    20. // 找到根节点的索引
    21. int rootIndex = valueIndexMap.get(rootValue);
    22. // 左子树节点数量
    23. int leftSize = rootIndex - inLeftIndex;
    24. // 构建根节点
    25. TreeNode root = new TreeNode(rootValue);
    26. // 左子树中序遍历序列起始索引
    27. int leftNextInLeftIndex = inLeftIndex;
    28. // 左子树中序遍历序列结束索引
    29. int leftNextInRightIndex = inLeftIndex + leftSize - 1;
    30. // 左子树后序遍历序列起始索引
    31. int leftNextPostLeftIndex = postLeftIndex;
    32. // 左子树后序遍历序列结束索引
    33. int leftNextPostRightIndex = postLeftIndex + leftSize - 1;
    34. // 构建左子树
    35. root.left = buildTree(inorder, postorder,
    36. leftNextInLeftIndex, leftNextInRightIndex,
    37. leftNextPostLeftIndex, leftNextPostRightIndex,
    38. valueIndexMap);
    39. // 右子树中序遍历序列起始索引
    40. int rightNextInLeftIndex = rootIndex + 1;
    41. // 右子树中序遍历序列结束索引
    42. int rightNextInRightIndex = inRightIndex;
    43. // 右子树后序遍历序列起始索引
    44. int rightNextPostLeftIndex = postLeftIndex + leftSize;
    45. // 右子树后序遍历序列结束索引
    46. int rightNextPostRightIndex = postRightIndex - 1;
    47. // 构建右子树
    48. root.right = buildTree(inorder, postorder,
    49. rightNextInLeftIndex, rightNextInRightIndex,
    50. rightNextPostLeftIndex, rightNextPostRightIndex,
    51. valueIndexMap);
    52. return root;
    53. }