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. [蓝桥杯]PREV-21.历届试题_回文数字

    问题描述 观察数字:, 都有一个共同的特征,无论从左到右读还是从右向左读,都是相同的.这样的数字叫做:回文数字. 本题要求你找到一些5位或6位的十进制数字.满足如下要求: 该数字的各个数位之和等于输入 ...

  2. LAB1 partII

    PartII   实现单词统计 实现 main/wc.go 两个函数 mapF() . reduceF() 单词是任意字母连续序列, 由unicode.IsLetter 决定字母 测试数据 pg-*. ...

  3. java 中的强制转换

    强制转换分两种,一种是基础类型强制转换(Type Conversion),一种是引用类型强制转换(Class Casting):

  4. MVC动态赋值的td选中,获取当前的td的ID或者值

    前台绑定数据: <div class="mailbox-content"> <table class="table"> <tbod ...

  5. VC工程产生文件后缀名解释

    [原文出自http://hi.baidu.com/zj0932zj/blog/item/b55f33cc7753c01700e92870.html ] .APS:存放二进制资源的中间文件,VC把当前资 ...

  6. leetcode《按递增顺序显示卡牌》

    题目描述: 牌组中的每张卡牌都对应有一个唯一的整数.你可以按你想要的顺序对这套卡片进行排序. 最初,这些卡牌在牌组里是正面朝下的(即,未显示状态). 现在,重复执行以下步骤,直到显示所有卡牌为止: 从 ...

  7. mysql 关联

    自关联 设计省信息的表结构provinces id ptitle 设计市信息的表结构cityscitys表的proid表示城市所属的省,对应着provinces表的id值 id ctitle proi ...

  8. 聊一聊Java泛型的擦除

    最近看了<thinking in java>的第十五章泛型,感觉有些东西需要记录下来. 泛型是Java SE5才被引入的概念,现在我的工作中泛型主要使用在集合,这样可以知道set()和ge ...

  9. 如何在vs2015中编译并配置tesseract4.0

    1)安装相关软件: 下载ccpan,把路径放到path(右击电脑,选择“属性”,选择左边的“高级系统设置”,选择“环境变量”,找到“系统变量”里面的“path”,点击“编辑”,选择右边的“新建”,输入 ...

  10. [leetcode]332. Reconstruct Itinerary

    Given a list of airline tickets represented by pairs of departure and arrival airports [from, to], r ...