106_从中序与后序遍历序列构造二叉树

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);
    }
}

 

posted @ 2021-12-19 23:55  一乐乐  阅读(30)  评论(0编辑  收藏  举报