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. Optaplanner规划引擎的工作原理及简单示例(1)

    在之前的文章中,老猿已介绍过APS及规划的相关内容,也对Optaplanner相关的概念和一些使用示例进行过介绍,接下来的文章中,我会自己做一个规划小程序 - 一个关于把任务分配到不同的机台上进行作来 ...

  2. HTML5 新的 Input 类型

    Input 类型: color(拾色器) color 类型用在input字段主要用于选取颜色,如下所示: 支持浏览器 实例 从拾色器中选择一个颜色: 选择你喜欢的颜色: <input type= ...

  3. LAB1 partV

    partV 创建文档反向索引.word -> document 与 前面做的 单词统计类似,这个是单词与文档位置的映射关系. mapF 文档解析相同,返回信息不同而已. reduceF 返回归约 ...

  4. 招聘IT图书兼职作者(长期兼职)

    招聘图书兼职作者(长期兼职),本公司有十多年的计算机图书出版经验,每年出版上百本编程类图书, 和清华大学出版社 电子工业出版社 机械工业出版社都有很好的合作.你可以不用按时上线,不用天天被boss盯着 ...

  5. 双网卡单IP实现网卡冗余与负载均衡

    WINDOWS下: 所谓双网卡,就是通过软件将双网卡绑定为一个IP地址,这个技术对于许多朋友来说并不陌生,许多高档服务器网卡(例如intel8255x系列.3COM服务器网卡等)都具有多网卡绑定功能, ...

  6. cassert(assert.h)——1个

    http://www.cplusplus.com/reference/cassert/assert/ 声明:void assert (int expression); #include <ios ...

  7. ActiveMQ( 一) 同步,异步,阻塞 JMS 消息模型

    同步请求:浏览器 向服务器 发送一个登录请求,如果服务器 没有及时响应,则浏览器则会一直等待状态,直至服务器响应或者超时. 异步请求:浏览器 向服务器 发送一个登录请求,不管服务器是否立即响应,浏览器 ...

  8. Unity Input,生命周期,Light,获取组件

    1.     递归方法遍历获取指定子物体 知识点:递归的使用:transform.childCount.GetChild(index) 2.  Input输入控制类,检测玩家输入 知识点: Input ...

  9. 适用于移动设备弹性布局的js脚本(rem单位)

    背景介绍 目前,随着移动设备的普及和4G网络的普及,web在移动端的占比已经远远超过PC端,各种H5页面推广页面,H5小游戏热度火爆.以前简单的使用px单位(没有弹性)的时代已经无法满足各位设计师和用 ...

  10. 在Spring Boot中使用 @ConfigurationProperties 注解

    但 Spring Boot 提供了另一种方式 ,能够根据类型校验和管理application中的bean. 这里会介绍如何使用@ConfigurationProperties.继续使用mail做例子. ...