LeetCode--106.从中序与后序遍历序列构造二叉树(二叉树)

题目描述

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

示例 1:

复制代码
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]

示例 2:

复制代码
输入:inorder = [-1], postorder = [-1]
输出:[-1]

提示:

  • 1 <= inorder.length <= 3000
  • postorder.length == inorder.length
  • -3000 <= inorder[i], postorder[i] <= 3000
  • inorder 和 postorder 都由 不同 的值组成
  • postorder 中每一个值都在 inorder 中
  • inorder 保证是树的中序遍历
  • postorder 保证是树的后序遍历

解题思路


代码

构造新数组

java 复制代码
/**
 * 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 {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        if(inorder == null) return null;
        // 在后序数组中找到最后一个元素
        int rootVal = postorder[postorder.length - 1];
        
        TreeNode root = new TreeNode(rootVal);
        // 已经是叶子结点
        if(postorder.length == 1) return root;
        // 在中序遍历中找到根节点下标
        int indexOfRoot = 0;
        for(int i=0; i<inorder.length; i++){
            if(inorder[i] == rootVal){
                indexOfRoot = i;
                break;
            }
        }
        // 切割中序遍历的左右子树
        int[] leftInOrder = new int[indexOfRoot];
        // 构造左子树中序遍历数组
        if(indexOfRoot != 0){
            for(int i=0; i<indexOfRoot; i++){
                leftInOrder[i] = inorder[i];
            }
        }else{
            leftInOrder = null;        
        } 
        // 构造右子树中序遍历数组
        int rightSize = inorder.length - indexOfRoot - 1;
        int[] rightInOrder = new int[rightSize];
        if(rightSize != 0){
            for(int i=0; i<rightSize; i++){
                rightInOrder[i] = inorder[i+indexOfRoot+1];
            }
        }else{
            rightInOrder = null;        
        }  
    
        // 切割后序遍历的左右子树
        int[] leftPostOrder = new int[indexOfRoot];
        // 构造左子树后序遍历数组
        if(indexOfRoot != 0){
            for(int i=0; i<indexOfRoot; i++){
                leftPostOrder[i] = postorder[i];
            }
        }else{
            leftPostOrder = null;        
        } 
        int[] rightPostOrder = new int[rightSize];
        // 构造右子树后序遍历数组
        if(rightSize != 0){
            for(int i=0; i<rightSize; i++){
                rightPostOrder[i] = postorder[i+indexOfRoot];
            }
        }else{
            rightPostOrder = null;        
        }  
        TreeNode leftChild = buildTree(leftInOrder, leftPostOrder);
        TreeNode rightChild = buildTree(rightInOrder, rightPostOrder);
        root.left = leftChild;
        root.right = rightChild;
        return root;
    }
}

记录下标法

java 复制代码
/**
 * 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 {

    public TreeNode buildHelper(int[] inorder, int inorderStart, int inorderEnd, int[] postorder, int postorderStart, int postorderEnd){
        if(inorderEnd < inorderStart || postorderEnd < postorderStart) return null;
        // 在后序数组中找到最后一个元素
        int rootVal = postorder[postorderEnd];
        
        TreeNode root = new TreeNode(rootVal);
        // 已经是叶子结点
        if(postorderEnd == 0) return root;
        // 在中序遍历中找到根节点下标
        int indexOfRoot = inorderStart;
        for(int i = inorderStart; i <= inorderEnd; i++){
            if(inorder[i] == rootVal){
                indexOfRoot = i;
                break;
            }
        }
        // 切割中序遍历的左右子树
        // 构造左子树中序遍历数组
        int leftInOrderStart = inorderStart;
        int leftInOrderEnd = indexOfRoot - 1;
        // 构造右子树中序遍历数组
        int rightInOrderStart = indexOfRoot + 1;
        int rightInOrderEnd = inorderEnd;

        // 切割后序遍历的左右子树
        int leftSize = indexOfRoot - inorderStart;
        // 构造左子树后序遍历数组
        int leftPostOrderStart = postorderStart;
        int leftPostOrderEnd = postorderStart + leftSize - 1;
        // 构造右子树后序遍历数组
        int rightPostOrderStart = postorderStart + leftSize;
        int rightPostOrderEnd = postorderEnd - 1;
        TreeNode leftChild = buildHelper(inorder, leftInOrderStart, leftInOrderEnd, postorder, leftPostOrderStart, leftPostOrderEnd);
        TreeNode rightChild = buildHelper(inorder, rightInOrderStart, rightInOrderEnd, postorder, rightPostOrderStart, rightPostOrderEnd);
        root.left = leftChild;
        root.right = rightChild;
        return root;
    }

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        if(inorder == null) return null;
        return buildHelper(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
    }
}

Map记录中序遍历

java 复制代码
/**
 * 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<Integer, Integer> map = new HashMap<>();

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        if(inorder.length == 0) return null;
        // 因为每次都需要从先序遍历中找到中间节点进行切分 做成map
        for(int i=0; i<inorder.length; i++){
            // 值为key 下标为value
            map.put(inorder[i],i);
        }
        return buildHelper(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
    }

    // 左闭右闭区间
    public TreeNode buildHelper(int[] inorder, int inorderStart, int inorderEnd, int[] postorder, int postorderStart, int postorderEnd){
        // 终止条件 数组越界
        if(inorderEnd < inorderStart || postorderEnd < postorderStart) return null;
        // 在后序数组中找到最后一个元素
        int rootVal = postorder[postorderEnd];
        TreeNode root = new TreeNode(rootVal);
        // 已经是叶子结点
        if(postorderEnd == 0) return root;
        // 在中序遍历中找到根节点下标
        int indexOfRoot = map.get(rootVal);

        int leftSize = indexOfRoot - inorderStart;

        TreeNode leftChild = buildHelper(inorder, inorderStart, indexOfRoot - 1, postorder, postorderStart, postorderStart + leftSize - 1);
        TreeNode rightChild = buildHelper(inorder, indexOfRoot + 1, inorderEnd, postorder, postorderStart + leftSize, postorderEnd - 1);
        root.left = leftChild;
        root.right = rightChild;
        return root;
    }
}
相关推荐
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼3 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark3 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her13 天前
并查集-听课笔记
笔记·算法·并查集
码流子3 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven3 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark3 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218613 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法