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

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

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

    递归算法框架:

    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. }
    1. 1
    2. / \
    3. 2 3
    4. / \ / \
    5. 4 5 6 7
    6. 前序遍历序列:[1, 2, 4, 5, 3, 6, 7]
    7. 后序遍历序列:[4, 5, 2, 6, 7, 3, 1]

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

    1. public TreeNode buildTree(int[] preorder, int[] postorder,
    2. int preStart, int leftPreEnd,
    3. int postStart, int postEnd) {
    4. // 找到根节点的值
    5. int rootValue = ?;
    6. // 构建根节点
    7. TreeNode root = new TreeNode(rootValue);
    8. // 构建左子树
    9. root.left = buildTree(preorder, postorder, ?, ?, ?, ?);
    10. // 构建右子树
    11. root.right = buildTree(preorder, postorder, ?, ?, ?, ?);
    12. return root;
    13. }

    889. 从前序与后序遍历序列构造二叉树 - 图2

    1. public TreeNode constructFromPrePost(
    2. int[] preorder, int[] postorder,
    3. int preStart, int preEnd,
    4. int postStart, int postEnd) {
    5. // 根节点值
    6. int rootValue = preorder[preStart];
    7. // 根节点索引
    8. int rootIndex = preStart;
    9. // 计算左子树 leftSize
    10. // 前序序列第二个元素是左子树根节点
    11. // 后序序列中和左子树根节点值相同的元素索引即左子树后序遍历序列右侧值
    12. int leftSize = 0;
    13. for (int i = postStart; i < postEnd; i++) {
    14. if (postorder[i] == preorder[rootIndex + 1]) {
    15. leftSize = i - postStart + 1;
    16. }
    17. }
    18. // 构建根节点
    19. TreeNode root = new TreeNode(rootValue);
    20. // 左子树 preStart
    21. int leftPreStart = rootIndex + 1;
    22. // 左子树 preEnd
    23. int leftPreEnd = leftPreStart + leftSize - 1;
    24. // 左子树 postStart
    25. int leftPostStart = postStart;
    26. // 左子树 postEnd
    27. int leftPostEnd = leftPostStart + leftSize - 1;
    28. // 构建左子树
    29. root.left = constructFromPrePost(preorder, postorder, leftPreStart, leftPreEnd, leftPostStart, leftPostEnd);
    30. // 右子树 preStart
    31. int rightPreStart = preStart + leftSize + 1;
    32. // 右子树 preEnd
    33. int rightPreEnd = preEnd;
    34. // 右子树 postStart
    35. int rightPostStart = postStart + leftSize;
    36. // 右子树 postEnd
    37. int rightPostEnd = postEnd - 1;
    38. // 构建右子树
    39. root.right = constructFromPrePost(preorder, postorder, rightPreStart, rightPreEnd, rightPostStart, rightPostEnd);
    40. return root;
    41. }
    42. public TreeNode constructFromPrePost(int[] preorder, int[] postorder) {
    43. return constructFromPrePost(preorder, postorder, 0, preorder.length - 1, 0, postorder.length - 1);
    44. }