超容易理解+模版套路解决LeetCode 前序+中序、中序+后序、前序+后序遍历构造树问题

这三道题的解法类似 都是基于归并排序的分治思想 不断划分左右子树进行解答。下列题1和题2解法几乎完全相同 题三根据前序后序遍历的话需要加以注意 后面详细讲解

LeetCode-105. 从前序与中序遍历序列构造二叉树

原题链接

题目描述

给定两个整数数组 preorderinorder

  • preorder 是二叉树的 前序遍历 序列。
  • inorder 是同一棵树的 中序遍历 序列。

请根据这两个数组 构造 出该二叉树,并返回其根节点。


示例展示

示例 1:

输入:
preorder = [3, 9, 20, 15, 7]
inorder = [9, 3, 15, 20, 7]

输出:
[3, 9, 20, null, null, 15, 7]

示例 2:

输入:
preorder = [-1]
inorder = [-1]

输出:
[-1]


提示条件

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorderinorder无重复 元素。
  • inorder 中的所有元素均出现在 preorder 中。
  • preorder 保证为二叉树的前序遍历序列。
  • inorder 保证为二叉树的中序遍历序列。

解题思路

根据前序遍历和中序遍历的特点可知 前序遍历是中->左->右,中序遍历是左 ->中->右,那根据两个遍历的特点 我们就可以想到:通过前序遍历来确定中间节点 然后通过中序遍历来划分左右节点 然后通过回溯把树串起来即可 多说无益 直接上代码展示

代码

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 {
    //记录preorder走到哪里了
    int index = 0;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return dfs(preorder,inorder,0,preorder.length-1);
    }
    public TreeNode dfs(int[] preorder,int[] inorder,int left,int right){
        if(left>right){
            return null;
        }
        int mid = 0;
        //找出用于划分左右子树的根节点
        for(int i = left;i<=right;i++){
            if(inorder[i]==preorder[index]){
                mid = i;
                break;
            }
        }
        TreeNode root = new TreeNode(preorder[index]);
        index++;
        //注意顺序 先序遍历是先左节点后右边
        root.left = dfs(preorder,inorder,left,mid-1);
        root.right = dfs(preorder,inorder,mid+1,right);
        return root;
    }
}

注意:root左右节点赋值的顺序要根据先序还是后序遍历来调整 下面第二题也就是这里做出了调整


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

原题链接

题目描述

给定两个整数数组 inorderpostorder

  • inorder 是二叉树的 中序遍历 序列。
  • postorder 是同一棵树的 后序遍历 序列。

请根据这两个数组 构造 出该二叉树,并返回其根节点。


示例展示

示例 1:

输入:
inorder = [9, 3, 15, 20, 7]
postorder = [9, 15, 7, 20, 3]

示例 2:

输入:
inorder = [-1]
postorder = [-1]

输出:
[-1]


提示条件

  • 1 <= inorder.length <= 3000
  • postorder.length == inorder.length
  • -3000 <= inorder[i], postorder[i] <= 3000
  • inorderpostorder 都由 不同 的值组成。
  • 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 {
    //记录postorder走到哪里了
    int index;
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        index = inorder.length-1;
        return dfs(inorder,postorder,0,inorder.length-1);
    }
    public TreeNode dfs(int[] inorder,int[] postorder,int left,int right){
        if(left>right){
            return null;
        }
        int mid = 0;
        //找出用于划分左右子树的根节点
        for(int i=left;i<=right;i++){
            if(inorder[i]==postorder[index]){
                mid = i;
                break;
            }
        }
        TreeNode root = new TreeNode(postorder[index]);
        index--;
        //注意好顺序 后序遍历是先访问右节点再访问左节点
        root.right = dfs(inorder,postorder,mid+1,right);
        root.left = dfs(inorder,postorder,left,mid-1);
        return root;
    }
}

以下是为您优化后的 889. 根据前序与后序遍历序列构造二叉树 的 Markdown 样式:


LeetCode-889. 根据前序与后序遍历序列构造二叉树

原题链接

题目描述

给定两个整数数组 preorderpostorder

  • preorder 是具有 无重复 值的二叉树的 前序遍历 序列。
  • postorder 是同一棵树的 后序遍历 序列。

请根据这两个数组 重构 出该二叉树,并返回其根节点。如果存在多个答案,您可以返回其中 任何一个


示例展示

示例 1:

输入:
preorder = [1, 2, 4, 5, 3, 6, 7]
postorder = [4, 5, 2, 6, 7, 3, 1]

输出:
[1, 2, 3, 4, 5, 6, 7]

示例 2:

输入:
preorder = [1]
postorder = [1]

输出:
[1]


提示条件

  • 1 <= preorder.length <= 30
  • 1 <= preorder[i] <= preorder.length
  • preorder 中所有值都 不同
  • postorder.length == preorder.length
  • 1 <= postorder[i] <= postorder.length
  • postorder 中所有值都 不同
  • 保证 preorderpostorder 是同一棵二叉树的有效遍历序列。

解题思路

这题和前两题略有不同 前两题可以根据中序遍历来区分左右子树 但是这题并没有明确的中间节点可以用 因此不能像前两题一样到下一层递归的时候再找"接班人" 要提前去找好 不同点就在这里 其余的还是模版代码

代码

java 复制代码
class Solution {
    int index = 0; // 前序从 0 开始
    public TreeNode constructFromPrePost(int[] preorder, int[] postorder) {
        return dfs(preorder, postorder, 0, postorder.length - 1);
    }

    public TreeNode dfs(int[] preorder, int[] postorder, int left, int right) {
        if (left > right) return null;

        // 1. 取出当前前序指针指向的值作为根
        TreeNode root = new TreeNode(preorder[index]);
        index++; // 消耗当前根
        
        // 【核心特殊点 1】:叶子检查
        // 如果 left == right,说明当前范围就这一个数,且已经被 new 过了,
        // 后面已经没有"左子树根"可以找了,必须直接返回,否则 index 会越界。
        if (left == right) return root;

        // 2. 【核心特殊点 2】:找"接班人"
        // 此时 index 已经指向了下一个数,它是【左子树的根】
        // 我们去后序数组里找这个"左根"的位置 mid
        int mid = 0;
        for (int i = left; i <= right; i++) {
            if (postorder[i] == preorder[index]) {
                mid = i;
                break;
            }
        }

        // 3. 划分边界
        // 左子树:从 left 到 mid(后序中左子树根是左侧部分的最后一个,所以含 mid)
        root.left = dfs(preorder, postorder, left, mid);
        // 右子树:从 mid+1 到 right-1(必须减 1 是因为要把后序数组末尾的当前根踢出去)
        root.right = dfs(preorder, postorder, mid + 1, right - 1);

        return root;
    }
}

以上就是这三道题的总结 有疑问的话欢迎小伙伴们提问~

相关推荐
wanderist.1 小时前
算法模板-线段树
c++·算法
lcj25111 小时前
蓝桥杯C++梳理(1):从入门到数组
c++·算法
sali-tec1 小时前
C# 基于OpenCv的视觉工作流-章26-图像拼接
图像处理·人工智能·opencv·算法·计算机视觉
wanderist.1 小时前
算法模板-01trie数
c++·算法
蜗牛^^O^2 小时前
如何负责一个系统的稳定性
java
一只叫煤球的猫2 小时前
别再把 Lambda 当匿名类:这 9 类坑你一定踩过
java·后端·面试
知识即是力量ol2 小时前
微服务架构:从入门到进阶完全指南
java·spring cloud·微服务·nacos·架构·gateway·feign
Javatutouhouduan2 小时前
RocketMQ是怎么保存偏移量的?
java·消息队列·rocketmq·java面试·消息中间件·后端开发·java程序员