leetcode106-从中序与后序遍历序列构造二叉树

原题

根据一棵树的中序遍历与后序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

中序遍历 inorder = [9,3,15,20,7] 后序遍历 postorder = [9,15,7,20,3]

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

解法

思想

根据后序遍历最后一个元素是根、中序遍历以根为中心划分左子树和右子树的特点,递归构造左子树和右子树。

代码

我们逐渐来优化时间复杂度:

第一版,较好懂:

class Solution {
    public int indexOf(int target,int[] order){
        for(int i = 0;i<order.length;i++){
            if(order[i] == target) return i;
        }
        return -1;
    }
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        if(postorder.length == 0) return null;
        TreeNode root = getUnit(inorder,postorder);
        return root;
    }
    public TreeNode getUnit(int[] inorder,int[] postorder){
        if(postorder.length == 0) return null;
        TreeNode root = new TreeNode(postorder[postorder.length-1]);
        int index = indexOf(postorder[postorder.length-1],inorder);
        int[] leftpartInorder = Arrays.copyOfRange(inorder,0,index);
        int[] rightpartInorder = Arrays.copyOfRange(inorder,index+1,inorder.length);
        int leftCount = leftpartInorder.length;
        int[] leftpartPostorder = Arrays.copyOfRange(postorder,0,leftCount);
        int[] rightpartPostorder = Arrays.copyOfRange(postorder,leftCount,postorder.length-1);
        root.left = getUnit(leftpartInorder,leftpartPostorder);
        root.right = getUnit(rightpartInorder,rightpartPostorder);
        return root;
    }
}

第二版,不用再复制数组,直接在原数组上操作:

class Solution {
    int[] inorderGlobal;
    int[] postorderGlobal;
    public int indexOf(int target,int start,int end){
        for(int i = 0;i<end-start;i++){
            if(inorderGlobal[i+start] == target) return i+start;
        }
        return -1;
    }
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        inorderGlobal = inorder;
        postorderGlobal = postorder;
        if(postorder.length == 0) return null;
        TreeNode root = getUnit(0,inorder.length,0,postorder.length);
        return root;
    }
    public TreeNode getUnit(int inorderStart,int inorderEnd,int postorderStart,int postorderEnd){
        if(postorderEnd==postorderStart) return null;
        TreeNode root = new TreeNode(postorderGlobal[postorderEnd-1]);
        int index = indexOf(postorderGlobal[postorderEnd-1],inorderStart,inorderEnd);
        int leftCount = index-inorderStart;
        root.left = getUnit(inorderStart,index,postorderStart,leftCount+postorderStart);
        root.right = getUnit(index+1,inorderEnd,postorderStart+leftCount,postorderEnd-1);
        return root;
    }
}

第三版,既然经常要用查找元素在中序遍历中的位置,可以不需要使用indexOf函数,而是一开始则将对应关系保存在哈希表中:

class Solution {
    int[] postorderGlobal;
    Map<Integer,Integer> map;
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        postorderGlobal = postorder;
        map = new HashMap<>();
        for(int i = 0;i < inorder.length; i++) map.put(inorder[i], i);
        if(postorder.length == 0) return null;
        TreeNode root = getUnit(0,inorder.length,0,postorder.length);
        return root;
    }
    public TreeNode getUnit(int inorderStart,int inorderEnd,int postorderStart,int postorderEnd){
        if(postorderEnd==postorderStart) return null;
        TreeNode root = new TreeNode(postorderGlobal[postorderEnd-1]);
        int index = map.get(postorderGlobal[postorderEnd-1]);
        int leftCount = index-inorderStart;
        root.left = getUnit(inorderStart,index,postorderStart,leftCount+postorderStart);
        root.right = getUnit(index+1,inorderEnd,postorderStart+leftCount,postorderEnd-1);
        return root;
    }
}

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/leetcode106-%e4%bb%8e%e4%b8%ad%e5%ba%8f%e4%b8%8e%e5%90%8e%e5%ba%8f%e9%81%8d%e5%8e%86%e5%ba%8f%e5%88%97%e6%9e%84%e9%80%a0%e4%ba%8c%e5%8f%89%e6%a0%91/

(0)
彭晨涛彭晨涛管理者
上一篇 2020年1月12日
下一篇 2020年1月13日

相关推荐

  • leetcode387-字符串中的第一个唯一字符

    原题 给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。 案例: s = "leetcode" 返回 0. s = "loveleetcode"…

    算法 2019年12月22日
    0130
  • leetcode23-合并K个排序链表

    原题 合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->…

    算法 2020年2月4日
    0170
  • leetcode73-矩阵置零

    原题 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。 示例 1: 输入: [   [1,1,1],  …

    算法 2020年5月14日
    090
  • leetcode39-组合总和

    原题 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates …

    2020年5月1日
    02730
  • leetcode236-二叉树的最近公共祖先

    原题 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 …

    2020年1月15日
    070
  • leetcode200-岛屿数量

    原题 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水…

    算法 2019年11月24日
    0150
  • leetcode16-最接近的三数之和

    原题 给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存…

    算法 2020年5月4日
    080
  • leetcode331-验证二叉树的前序序列化

    原题 序列化二叉树的一种方法是使用前序遍历。当我们遇到一个非空节点时,我们可以记录下这个节点的值。如果它是一个空节点,我们可以使用一个标记值记录,例如 #。 _9_ / \ 3 2…

    算法 2020年1月26日
    090
  • leetcode239-滑动窗口最大值

    原题 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最…

    算法 2020年4月21日
    0180
  • leetcode392-判断子序列

    原题 https://leetcode.cn/problems/is-subsequence/description 解法 最简单的双指针略。 对于进阶场景:如果有大量输入的 S,…

    算法 2024年3月24日
    030

发表回复

登录后才能评论