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. 如何重置Gitlab root用户密码

    一.切换到root用户 sudo su 二.进入gitlab控制台 gitlab-rails console production 三.查找用户对象 user = User.).first 四.重置密 ...

  2. IDEA 运行spring boot出现端口占用的问题

    Description: The Tomcat connector configured to listen on port 8080 failed to start. The port may al ...

  3. WinSDK-键盘消息

    一 参考url http://www.cnblogs.com/5iedu/p/4656178.html http://blog.csdn.net/yiyefangzhou24/article/deta ...

  4. xshell完美开源替代方案(Kitty+MTPuTTY并设置全局字体)

    xshell是收费的,过了30天就不能用了.我们应该找一个开源的替代品.说实话windows平台没有什么可选的,就是putty.但是原生的putty不好用,记不住密码,又不支持多标签. Kitty是基 ...

  5. node_api学习之http

    node模块学习-http 理解 HTTP构建于TCP之上,属于应用层协议,继承自tcp服务器(net模块),它能与多个客户端保持连接,由于基于事件驱动,并不为每个连接创建额外的进程或线程,所以能实现 ...

  6. sqlserver查找使用了某个字段的所有存储过程

    当一个系统中使用了很多的表,并且存在大量的存储过程,当数据库中的某个表删除了某个字段,那么相应的存储过程也需要改动,但是我们不知道哪些存储过程使用了该字段,那我们该怎么办?我们可以从之前的文档一个一个 ...

  7. vue搜索功能

    <!DOCTYPE html><html><head><meta charset="utf-8"><title>Vue测 ...

  8. Windows根证书的批量导出和导入

    # POWERSHELL批量导出 Get-ChildItem -Path Cert:\LocalMachine\Root\ |ForEach-Object {Export-Certificate -C ...

  9. Android 开发 获取Android设备的屏幕高宽

    获得屏幕的宽度和高度有很多种方法: //1.通过WindowManager获取 DisplayMetrics dm = new DisplayMetrics(); heigth = dm.height ...

  10. 爬虫基础——HTTP基本原理

    ## 学习爬虫务必从了解请求网页的工作流程和网页的组成原理开始,不然直接去学爬虫操作像是请求库等等,大概率会知其然而不知其所以然(个人体会) URL和HTTP简介 URL(Uniform Resour ...