树的遍历 之 用中序和后序遍历序列构建二叉树

337 阅读2分钟

本文正在参与掘金团队号上线活动,点击 查看大厂春招职位

一、题目描述:

这个题目说的是,给你一棵二叉树的中序和后序遍历序列,你要根据这两个序列构建这棵二叉树。假设这棵二叉树节点上没有重复的数字。

比如说,给你的中序遍历序列和后序遍历序列分别是:

中序遍历序列:2, 1, 8, 4, 16
后序遍历序列:2, 8, 16, 4, 1

你要返回用它们构建出的二叉树,是:

    1
  /   \
 2     4
      / \
     8  16

二、思路分析:

解题步骤:

  1. 先找到根节点:在后序数组
  2. 再左右两边递归构造:在中序数组

可以使用一个 Map 存储中序遍历的值和下标,用于快速访问。


三、AC 代码:

public class LeetCode_106 {
    
     public class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) {
            val = x;
        }
    }

    // Time: o(n), Space: o(n), Faster: 66.41%
    public TreeNode buildTree(int[] inorder, int[] postorder) {

        Map<Integer, Integer> inPos = new HashMap<>();

        for (int i = 0; i < inorder.length; ++i)
            inPos.put(inorder[i], i);

        return buildTree(postorder, 0, postorder.length - 1, 0, inPos);
    }

    private TreeNode buildTree(int[] post, int postStart, int postEnd, int inStart, Map<Integer, Integer> inPos) {

        if (postStart > postEnd) return null;

        TreeNode root = new TreeNode(post[postEnd]);
        int rootIdx = inPos.get(post[postEnd]);
        int leftLen = rootIdx - inStart;
        root.left = buildTree(post, postStart, postStart + leftLen - 1, inStart, inPos);
        root.right = buildTree(post, postStart + leftLen, postEnd - 1, rootIdx + 1, inPos);

        return root;
    }
}

四、总结:

树的遍历模板

树的遍历有四种:

  1. 前序遍历
  2. 中序遍历
  3. 后序遍历
  4. 层级遍历

这里也可以分为:深度优先遍历(DFS广度优先遍历 (BFS

层级遍历:是为广度优先遍历。

其他遍历:是为深度优先遍历。

1. 前序遍历

void traverse(TreeNode root) {
    if (null == root) return;
    
    // 前序遍历的代码
    
    traverse(root.left);
    traverse(root.right);
}

2. 中序遍历

void traverse(TreeNode root) {
    if (null == root) return;
    
    traverse(root.left);
    
    // 前序遍历的代码
    
    traverse(root.right);
}

3. 后序遍历

void traverse(TreeNode root) {
    if (null == root) return;
    
    traverse(root.left);
    traverse(root.right);
    
    // 前序遍历的代码
}

4. 层级遍历

用队列模拟

void traverse(TreeNode root) {
    if (null == root) return;
    
    // 初始化队列,将 root 加入队列
    Queue<TreeNode> q = new LinkedList<>();
    q.offer(root);
    
    while (!q.isEmpty()) {
        TreeNode cur = q.poll();
        
        // 层级遍历代码
        System.out.println(root.val);
        
        if (cur.left != null) q.offer(cur.left);
        if (cur.right != null) q.offer(cur.right);
    }
}