LeetCode 原题链接

题目大意

  1. 给定一棵二叉树的中序遍历和后序遍历,求这棵二叉树的结构。
  2. 给定一棵二叉树的前序遍历和中序遍历,求这棵二叉树的结构。

样例

  1. Input: inorder = [9, 3, 15, 20, 7], postorder = [9, 15, 7, 20, 3]
    Output: [3, 9, 20, null, null, 15, 7]
  2. Input: preorder = [3, 9, 20, 15, 7], postorder = [9, 3, 15, 20, 7]
    Output: [3, 9, 20, null, null, 15, 7]

解题思路

这两题的解题思路类似,主要应用了二叉树的这样一个结论:

对于任意一棵二叉树:

  • 其前序遍历序列的第一个元素为该树的根
  • 其后序遍历序列的最后一个元素为该树的根

然后对于一棵二叉树的遍历序列,其元素排布总是遵循如下规律:

  • 前序遍历:[根元素, [左子树元素], [右子树元素]]
  • 中序遍历:[[左子树元素], 根元素, [右子树元素]]
  • 后序遍历:[[左子树元素], [右子树元素], 根元素]

有了以上结论,这两题的思路就很明确了:先从前序(或后序)遍历中找到根元素,然后将遍历结果按照上面的元素分布规律分成三个部分,对于左子树和右子树,递归地调用该算法去构建,即可得出完整的结构。

根据以上思路,可以写出对数组进行分割的代码,记录如下:

  • 前序遍历:

    /// <summary>
    /// 把二叉树的前序遍历序列分拆成左右两部分
    /// 左右两部分中,若有一个部分不存在,则返回长度为 0 的数组
    ///
    /// 在调用该方法前,需要提前为左右两部分的数组分配空间(即需要左右子树的序列大小)
    /// </summary>
    /// <param name="sourceArray">一个数组,表示二叉树的前序遍历序列</param>
    /// <param name="leftPart">一个数组,表示这棵树的左子树的前序遍历序列</param>
    /// <param name="rightPart">一个数组,表示这棵树的右子树的前序遍历序列</param>
    private void SplitArray(int[] sourceArray, int[] leftPart, int[] rightPart)
    {
    // 对于前序遍历,各部分对应的下标范围为:
    // - [0, 1):根节点
    // - [1, 1 + leftPart.Length):左子树的前序遍历序列
    // - [1 + leftPart.Length, sourceArray.Length):右子树的遍历序列 // 复制左子树内容
    Array.Copy(sourceArray, 1, leftPart, 0, leftPart.Length);
    // 复制右子树内容
    Array.Copy(sourceArray, 1 + leftPart.Length, rightPart, 0, rightPart.Length);
    }
  • 中序遍历:

    /// <summary>
    /// 把二叉树的中序遍历序列分拆成左右两部分
    /// 左右两部分中,若有一个部分不存在,则返回长度为 0 的数组
    /// </summary>
    /// <param name="sourceArray">一个数组,表示二叉树的中序遍历序列</param>
    /// <param name="splitIndex">这棵二叉树的根节点,在中序遍历序列中的下标</param>
    /// <param name="leftPart">输出参数,表示这棵树的左子树的中序遍历序列</param>
    /// <param name="rightPart">输出参数,表示这棵树的右子树的中序遍历序列</param>
    void SplitArray(int[] sourceArray, int splitIndex, out int[] leftPart, out int[] rightPart)
    {
    // 为左右两部分分配空间
    // 对于中序遍历,各部分对应的下标范围为
    // - [0, splitIndex):左子树的中序遍历序列
    // - [splitIndex, splitIndex + 1):根节点
    // - [splitIndex + 1, sourceArray.Length):右子树的中序遍历序列
    leftPart = new int[splitIndex];
    rightPart = new int[sourceArray.Length - (splitIndex + 1)]; // 复制左子树内容
    Array.Copy(sourceArray, leftPart, leftPart.Length); // 复制右子树内容
    Array.Copy(sourceArray, splitIndex + 1, rightPart, 0, rightPart.Length);
    }
  • 后序遍历:

    /// <summary>
    /// 把二叉树的后序遍历序列分拆成左右两部分
    /// 左右两部分中,若有一个部分不存在,则返回长度为 0 的数组
    ///
    /// 在调用该方法前,需要提前为左右两部分的数组分配空间(即需要左右子树的序列大小)
    /// </summary>
    /// <param name="sourceArray">一个数组,表示二叉树的后序遍历序列</param>
    /// <param name="leftPart">一个数组,表示这棵树的左子树的后序遍历序列</param>
    /// <param name="rightPart">一个数组,表示这棵树的右子树的后序遍历序列</param>
    void SplitArray(int[] sourceArray, int[] leftPart, int[] rightPart)
    {
    // 对于后序遍历,各部分对应的下标范围为:
    // - [0, leftPart.Length):左子树的后序遍历
    // - [leftPart.Length, leftPart.Length + rightPart.Length):右子树的后序遍历
    // - [leftPart.Length + rightPart.Length, sourceArray.Length):根节点 // 复制左子树内容
    Array.Copy(sourceArray, leftPart, leftPart.Length);
    // 复制右子树内容
    Array.Copy(sourceArray, leftPart.Length, rightPart, 0, rightPart.Length);
    }

Solution

  • Construct Binary Tree from Inorder and Postorder Traversal

    /// <summary>
    /// 根据二叉树的中序遍历序列和后序遍历序列,构建这棵二叉树
    /// </summary>
    /// <param name="inorder">一个数组,表示二叉树的中序遍历序列</param>
    /// <param name="postorder">一个数组,表示二叉树的后序遍历序列</param>
    /// <returns>构建出的二叉树的根节点</returns>
    public TreeNode BuildTree(int[] inorder, int[] postorder)
    {
    // 递归终止条件:序列的长度为 0,返回 null
    if (inorder.Length == 0 || postorder.Length == 0)
    return null;
    // 从后序遍历序列中找到根节点的值
    int rootVal = postorder.Last();
    // 在中序遍历序列中找到根节点对应的下标,以便分出左右部分
    int rootIndex = Array.IndexOf(inorder, rootVal); // 提前为后序遍历的两部分分配内存空间
    int[] postorderLeft = new int[rootIndex - 0];
    int[] postorderRight = new int[inorder.Length - (rootIndex + 1)]; // 建立根节点
    TreeNode root = new TreeNode(rootVal); // 拆分中序遍历序列
    SplitArray(inorder, rootIndex, out int[] inorderLeft, out int[] inorderRight); // 拆分后序遍历序列
    SplitArray(postorder, postorderLeft, postorderRight); // 递归地调用该方法以构建左右子树
    root.left = BuildTree(inorderLeft, postorderLeft);
    root.right = BuildTree(inorderRight, postorderRight); return root;
    }
  • Construct Binary Tree from Preorder and Inorder Traversal

    /// <summary>
    /// 根据二叉树的中序遍历序列和前序遍历序列,构建这棵二叉树
    /// </summary>
    /// <param name="preorder">一个数组,表示二叉树的前序遍历序列</param>
    /// <param name="inorder">一个数组,表示二叉树的中序遍历序列</param>
    /// <returns>构建出的二叉树的根节点</returns>
    public TreeNode BuildTree(int[] preorder, int[] inorder)
    {
    // 递归终止条件:序列的长度为 0,返回 null
    if (inorder.Length == 0 || preorder.Length == 0)
    return null;
    // 从前序遍历序列中找到根节点的值
    int rootVal = preorder[0];
    // 在中序遍历序列中找到根节点对应的下标,以便分出左右部分
    int rootIndex = Array.IndexOf(inorder, rootVal); // 提前为前序遍历的两部分分配内存空间
    int[] preorderLeft = new int[rootIndex - 0];
    int[] preorderRight = new int[inorder.Length - (rootIndex + 1)]; // 建立根节点
    TreeNode root = new TreeNode(rootVal); // 拆分中序遍历序列
    SplitArray(inorder, rootIndex, out int[] inorderLeft, out int[] inorderRight); // 拆分前序遍历序列
    SplitArray(preorder, preorderLeft, preorderRight); // 递归地调用该方法以构建左右子树
    root.left = BuildTree(preorderLeft, inorderLeft);
    root.right = BuildTree(preorderRight, inorderRight); return root;
    }

【题解二连发】Construct Binary Tree from Inorder and Postorder Traversal & Construct Binary Tree from Preorder and Inorder Traversal的更多相关文章

  1. Leetcode Construct Binary Tree from Inorder and Postorder Traversal

    Given inorder and postorder traversal of a tree, construct the binary tree. Note:You may assume that ...

  2. 【LeetCode OJ】Construct Binary Tree from Inorder and Postorder Traversal

    Problem Link: https://oj.leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-trav ...

  3. leetcode-1006 Construct Binary Tree from Inorder and Postorder Traversal

    Given inorder and postorder traversal of a tree, construct the binary tree. Note:You may assume that ...

  4. 【LeetCode】106. Construct Binary Tree from Inorder and Postorder Traversal

    Construct Binary Tree from Inorder and Postorder Traversal Given inorder and postorder traversal of ...

  5. [LeetCode-21]Construct Binary Tree from Preorder and Inorder Traversal

    Given preorder and inorder traversal of a tree, construct the binary tree. Note: You may assume that ...

  6. leetcode题解:Construct Binary Tree from Preorder and Inorder Traversal (根据前序和中序遍历构造二叉树)

    题目: Given preorder and inorder traversal of a tree, construct the binary tree. Note:You may assume t ...

  7. leetcode题解:Construct Binary Tree from Inorder and Postorder Traversal(根据中序和后序遍历构造二叉树)

    题目: Given inorder and postorder traversal of a tree, construct the binary tree. Note:You may assume ...

  8. [LeetCode] Construct Binary Tree from Inorder and Postorder Traversal 由中序和后序遍历建立二叉树

    Given inorder and postorder traversal of a tree, construct the binary tree. Note: You may assume tha ...

  9. 【LeetCode】105 & 106. Construct Binary Tree from Inorder and Postorder Traversal

    题目: Given inorder and postorder traversal of a tree, construct the binary tree. Note:You may assume ...

随机推荐

  1. version `GLIBC_2.17' not found 解决方法

    1.先查看是哪个函数用的是GLIBC_2.17 root@emb-pc:/home/emb/temp# nm lib61850.so | grep GLIBC_2.17 U clock_gettime ...

  2. WCF服务could not be activated

    The requested service, 'http://10.10.10.143/XmlEditorService/XmlEditorService.svc' could not be acti ...

  3. SpringBoot 配置文件 中文乱码

    本方案,支持springboot 很简单 在配置文件中不写中文,写中文的ascll码 直接百度在线转ASCII,用工具 把中文转ASCII码==>\u628a\u4e2d\u6587\u8f6c ...

  4. Ubuntu系统配置

    0.基本配置 0.1初始设置 (1)开户root账号并重启系统: 打开gedit /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf 添加greeter- ...

  5. Spring boot 的application.properties 全局配置

    端口号.项目名称 application.properties: server.port=8888 server.context-path=/start 日志相关的配置 # 自定义日志配置路径 log ...

  6. 欢迎来到GitHub世界

    什么是GitHub GitHub(Pronunciation:/githʌb/)  这是一个为开发者提供Git仓库的托管服务,这是一个让开发者们共享代码的完美场所.GitHub公司总部位于美国旧金山, ...

  7. 【转】Lombok 安装、入门 - 消除冗长的 java 代码

    前言:    逛开源社区的时候无意发现的,用了一段时间,觉得还可以,特此推荐一下.    lombok 提供了简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 java 代码.特别是相对于 ...

  8. selenium测瀑布流UI页面的Python代码

    from  selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdri ...

  9. docker(ce) on Ubuntu

    Note: # - requires given linux commands to be executed with root privileges either directly as a roo ...

  10. python3csv与xlsx文件操作模块(csv、xlsxwriter)

    一.csv模块实现csv文件操作 1.CSV介绍 CSV,全称为Comma-Separated Values,它以逗号分隔值,其文件以纯文本形式存储表格数据,该文件是一个字符序列,可以由任意数目的记录 ...