package highFrequencyLeetcode.leetcode_105; import java.util.HashMap; import java.util.Map; /** *

* * 根据一棵树的前序遍历与中序遍历构造二叉树。 * * 注意: * 你可以假设树中没有重复的元素。 * * 例如,给出 * * 前序遍历 preOrder = [3, 9, 20, 15, 7] * 中序遍历 inOrder = [9, 3, 15, 20, 7] * * 返回如下的二叉树: * * 3 * / \ * 9 20 * / \ * 15 7 * *

* * @author Seina * @version 2019-06-24 23:39:47 */ public class ConstructBinaryTreeFromPreorderAndInorderTraversal { /** * 解法1 递归 * * 前序便利的第一个元素一定是树的根,然后这个根将中序遍历分成左右两颗子树,再通过移动指针递归两个子树,不停给左右子节点赋值,最后完成树的构建 * * @param preOrder: 前序遍历 * @param inOrder: 中序遍历 * @return 构建好树返回根节点 */ public TreeNode buildTree(int[] preOrder, int[] inOrder){ Map map = new HashMap(); for (int i = 0; i < inOrder.length; i++) map.put(inOrder[i], i); return build(preOrder, 0, preOrder.length - 1, inOrder, 0, inOrder.length - 1, map); } /** * @param pre : 前序遍历 preOrder * @param ps : preOrder start * @param pe : preOrder end * @param in : 中序遍历 inOrder * @param is : inOrder start * @param ie : inOrder end * @param map : inOrder map - key: 中序遍历数组元素 value: 元素数组下表 * @return 构建完成返回根节点 */ private TreeNode build(int[] pre, int ps, int pe, int[] in, int is, int ie, Map map) { if (ps > pe || is > ie) return null; //前序遍历的第一个元素一定是树的根 TreeNode root = new TreeNode(pre[ps]); //找到这个根在中序遍历中的位置,它将中序遍历分成了左右两颗子树 int rootIndex = map.get(root.val); //距离 = 根在中序遍历中的位置 - 左子节点的位置 int distance = rootIndex - is; /** * ps + 1 : 前序遍历中 - 左子树的开始节点 * ps + distance : 前序遍历中 - 左子树的结束节点 * is : 中序遍历中 - 左子树的开始节点 * rootIndex - 1 : 中序遍历中 - 左子树的结束节点 */ root.left = build(pre, ps + 1, ps + distance, in, is, rootIndex - 1, map); /** * ps + distance + 1 : 前序遍历中 - 右子树的开始节点 * pe : 前序遍历中 - 右子树的结束节点 * rootIndex + 1 : 中序遍历中 - 右子树的开始节点 * ie : 中序遍历中 - 右子树的结束节点 */ root.right = build(pre, ps + distance + 1, pe, in, rootIndex + 1, ie, map); return root; } }