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日

相关推荐

  • leetcode557-反转字符串中的单词III

    原题 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。 示例1: 输入: “Let’s take LeetCode contest” 输出: …

    算法 2019年11月23日
    0160
  • leetcode238-除自身以外数组的乘积

    原题 给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积…

    算法 2020年6月4日
    0110
  • leetcode131-分割回文串

    原题 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。 返回 s 所有可能的分割方案。 示例: 输入: "aab" 输出: [ ["aa","b"], …

    算法 2020年5月22日
    0120
  • leetcode392-判断子序列

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

    算法 2024年3月24日
    0460
  • leetcode682-棒球比赛

    原题 你现在是棒球比赛记录员。给定一个字符串列表,每个字符串可以是以下四种类型之一:1. 整数(一轮的得分):直接表示您在本轮中获得的积分数。2. "+"(一轮的得…

    算法 2020年2月3日
    0220
  • leetcode54-螺旋矩阵

    原题 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。 示例 1: 输入: [ [ 1, 2, 3 ], [ 4, 5, 6…

    算法 2019年11月15日
    0100
  • leetcode80-删除排序数组中的重复项II

    原题 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外…

    算法 2020年5月26日
    0160
  • leetcode540-有序数组中的单一元素

    原题 给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。 示例1: 输入: [1,1,2,3,3,4,4,8,8] 输出: 2 示例2: 输入…

    2020年2月25日
    0710
  • leetcode232-用栈实现队列

    原题 使用栈实现队列的下列操作: push(x) – 将一个元素放入队列的尾部。 pop() – 从队列首部移除元素。 peek() – 返回队列首部的元素。 empty() – …

    算法 2019年12月13日
    0560
  • leetcode373-查找和最小的K对数字

    原题 给定两个以升序排列的整形数组 nums1 和 nums2, 以及一个整数 k。 定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2。 找到和最…

    算法 2020年2月13日
    0170

发表回复

登录后才能评论