106_从中序与后序遍历序列构造二叉树
package 二叉树.BT; import java.util.ArrayList; import java.util.Deque; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/ * @author Huangyujun * */ public class _106_从中序与后序遍历序列构造二叉树 { public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() { } TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } } } /** * 大佬的代码启发:想要使用递归(当直接使用不了题目给的参数是,可以自己定义一个同名(参数自己定,然后不断的递归)),题意给的方法再调用该方法即可 ** TreeNode buildTree(int[] inorder, int[] postorder) 这个方法是题目本身 * public TreeNode buildTree(int is, int ie, int ps, int pe) 这个方法是自定义的 * 使用递归突破点:什么时候跳出return:往往看传入的参数的关系(当参数变化到不合理是即退出) */ class Solution { HashMap<Integer,Integer> memo = new HashMap<>(); int[] post; public TreeNode buildTree(int[] inorder, int[] postorder) { for(int i = 0;i < inorder.length; i++) memo.put(inorder[i], i); post = postorder; TreeNode root = buildTree(0, inorder.length - 1, 0, post.length - 1); return root; } //一个树:【中序遍历时的范围】【后序遍历的范围】 //该过程 获取到根,然后才划分出两颗树(左子树、右子树) public TreeNode buildTree(int is, int ie, int ps, int pe) { if(ie < is || pe < ps) return null; int root = post[pe]; int ri = memo.get(root); TreeNode node = new TreeNode(root); node.left = buildTree(is, ri - 1, ps, ps + ri - is - 1); node.right = buildTree(ri + 1, ie, ps + ri - is, pe - 1); return node; } } /** * 官网的思考角度即我的思考角度:尤其是:(参数是一棵树范围,然后先右子树再左子树): * 只是我还没有将思想更加清晰的转化成:树【范围用 中序表示】,后序最后一个元素用来取根结点(这也是为什么先右子树再左子树),因为后序是 左右 根, 右子树离最后一个位置最近 // 下标减一 post_idx--; // 构造右子树 root.right = helper(index + 1, in_right); // 构造左子树 root.left = helper(in_left, index - 1); * @author Huangyujun * */ class Solution2 { int post_idx; int[] postorder; int[] inorder; Map<Integer, Integer> idx_map = new HashMap<Integer, Integer>(); public TreeNode helper(int in_left, int in_right) { // 如果这里没有节点构造二叉树了,就结束 if (in_left > in_right) { return null; } // 选择 post_idx 位置的元素作为当前子树根节点 int root_val = postorder[post_idx]; TreeNode root = new TreeNode(root_val); // 根据 root 所在位置将中序分成左右两棵子树 int index = idx_map.get(root_val); // 下标减一 post_idx--; // 构造右子树 root.right = helper(index + 1, in_right); // 构造左子树 root.left = helper(in_left, index - 1); return root; } public TreeNode buildTree(int[] inorder, int[] postorder) { this.postorder = postorder; this.inorder = inorder; // 从后序遍历的最后一个元素开始 post_idx = postorder.length - 1; // 建立(元素,下标)键值对的哈希表 int idx = 0; for (Integer val : inorder) { idx_map.put(val, idx++); } return helper(0, inorder.length - 1); } }