JZ07. 重建二叉树(分治算法)

26 阅读1分钟

leetcode.cn/problems/zh…

输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

 

示例 1:

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] Output: [3,9,20,null,null,15,7] 示例 2:

Input: preorder = [-1], inorder = [-1] Output: [-1]  

限制:

0 <= 节点个数 <= 5000

解题思路:

image.png

image.png

通过以上三步,可确定 三个节点 :1.树的根节点、2.左子树根节点、3.右子树根节点。

根据「分治算法」思想,对于树的左、右子树,仍可复用以上方法划分子树的左右子树。

分治算法解析:

image.png

复杂度分析:

image.png

代码:

注意:本文方法只适用于 “无重复节点值” 的二叉树。

class Solution {
    int[] preorder;
    HashMap<Integer, Integer> inorderIndexMap = new HashMap<>();

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        this.preorder = preorder;
        for (int i = 0; i < inorder.length; i++) {
            inorderIndexMap.put(inorder[i], i);
        }
        return recur(0, 0, inorder.length - 1);
    }

    public TreeNode recur(int rootIndexInPreorder, int leftIndexInInorder, int rightIndexInInorder) {
        // 递归终止
        if (leftIndexInInorder > rightIndexInInorder) {
            return null;
        }
        // 建立根节点
        TreeNode rootTreeNode = new TreeNode(preorder[rootIndexInPreorder]);
        // 划分根节点、左子树、右子树
        int rootIndexInInorder = inorderIndexMap.get(rootTreeNode.val);
        // 开启左子树递归
        rootTreeNode.left = recur(rootIndexInPreorder + 1, leftIndexInInorder,
                rootIndexInInorder - 1);
        // 开启右子树递归
        rootTreeNode.right = recur(rootIndexInInorder - leftIndexInInorder +
                1 + rootIndexInPreorder, rootIndexInInorder + 1, rightIndexInInorder);
        // 回溯返回根节点
        return rootTreeNode;
    }
}