6.13从中序与后序遍历序列构造二叉树(LC106-M)

6.13从中序与后序遍历序列构造二叉树(LC106-M)_第1张图片

算法:

(前序+中序、后序+中序,都可以构造二叉树;若只知前序+后序,无法构造)

后序遍历(LRV)的最后一个值一定是根节点!

切割时,保证左闭右开的原则

  • 第一步:如果数组大小为零的话,说明是空节点了。

  • 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。

  • 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点

  • 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)

  • 第五步:切割后序数组,切成后序左数组和后序右数组

  • 第六步:递归处理左区间和右区间

调试过程:

/**
 * Definition for a binary tree node.
 * 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;
 *     }
 * }
 */
class Solution {
    //全局变量map
    Map map;
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        map = new hashmap<>();
        for (int i=0;i= inbegin || postend >= postbegin) return null;
        //后序遍历的最后一个节点一定是根节点!
        //map存储的是中序遍历的值以及索引,因此rootindex是根节点在中序遍历中的索引
        int rootindex = map.get(postorder[postend-1]);
        //分割:在前序遍历中构造根节点
        //root.left就是root的左边,root.right就是root的右边
        TreeNode root = new TreeNode(inorder[roootnode]);
        //保存中序左子树个数,用来确定后序数列的个数
        int leftnum = rootindex - inbegin;
        //左闭右开
        root.left = findnode(inorder, inbegin, rootindex, 
        postorder, postbegin, postbegin+leftnum);
        //左闭右开
        root.right = findnode(int[] inorder, int rootindex+1, int inend, 
        int[] postorder, int postbegin+leftnum, int postend-1);      
        return root;  

    }
}

6.13从中序与后序遍历序列构造二叉树(LC106-M)_第2张图片

原因:

定义过的参数在方法的参数列表中已经进行了声明和定义,所以在方法内部不需要再次使用 `int` 关键字进行定义。(已经定义过多参数直接引用即可,不用再次定义!)

另外,注意拼写错误:Integer HashMap length

正确代码:

/**
 * Definition for a binary tree node.
 * 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;
 *     }
 * }
 */
class Solution {
    //全局变量map
    Map map;
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        map = new HashMap<>();
        for (int i=0;i= inend || postbegin >= postend) return null;
        //后序遍历的最后一个节点一定是根节点!
        //map存储的是中序遍历的值以及索引,因此rootindex是根节点在中序遍历中的索引
        int rootindex = map.get(postorder[postend-1]);
        //分割:在前序遍历中构造根节点
        //root.left就是root的左边,root.right就是root的右边
        TreeNode root = new TreeNode(inorder[rootindex]);
        //保存中序左子树个数,用来确定后序数列的个数
        int leftnum = rootindex - inbegin;
        //左闭右开
        root.left = findnode(inorder, inbegin, rootindex, 
        postorder, postbegin, postbegin+leftnum);
        //左闭右开
        root.right = findnode(inorder, rootindex+1, inend, 
        postorder, postbegin+leftnum, postend-1);      
        return root;  

    }
}

时间空间复杂度

时间复杂度:

  • 在构建树的过程中,我们需要遍历中序遍历数组和后序遍历数组,构建哈希表以及递归构建子树。这些操作的时间复杂度都是线性的,即O(n),其中 n 是节点的数量。
  • 因此,总体上,构建二叉树的时间复杂度为 O(n)。

空间复杂度:

  • 在构建树的过程中,我们使用了一个哈希表来存储中序遍历数组中节点值和索引的映射关系。哈希表的空间复杂度是O(n),其中 n 是节点的数量。
  • 此外,递归过程中需要使用栈空间来保存递归调用的上下文,栈的空间复杂度取决于树的高度。在最坏情况下,树是一个单链表,高度为 n,因此栈的空间复杂度也是O(n)。
  • 综上所述,构建二叉树的空间复杂度为O(n)。

总结起来,这段代码的时间复杂度为 O(n),空间复杂度为 O(n)。

你可能感兴趣的:(#,6.二叉树,算法,数据结构)