【题解二连发】Construct Binary Tree from Inorder and Postorder Traversal & Construct Binary Tree from Preorder and Inorder Traversal
LeetCode 原题链接
- Construct Binary Tree from Inorder and Postorder Traversal - LeetCode
- Construct Binary Tree from Preorder and Postorder Traversal - LeetCode
题目大意
- 给定一棵二叉树的中序遍历和后序遍历,求这棵二叉树的结构。
- 给定一棵二叉树的前序遍历和中序遍历,求这棵二叉树的结构。
样例
Input: inorder = [9, 3, 15, 20, 7], postorder = [9, 15, 7, 20, 3]
Output: [3, 9, 20, null, null, 15, 7]
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的更多相关文章
- 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 ...
- 【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 ...
- 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 ...
- 【LeetCode】106. Construct Binary Tree from Inorder and Postorder Traversal
Construct Binary Tree from Inorder and Postorder Traversal Given inorder and postorder traversal of ...
- [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 ...
- 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 ...
- 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 ...
- [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 ...
- 【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 ...
随机推荐
- Java Socket NIO
服务端: public class NIOServer { private static final String HOST = "localhost"; private stat ...
- Chromium(Chrome) frame structure detail
1. Chromium VS Chrome Chromium is an open-source Web browser project started by Google, to provide t ...
- 涨姿势:Mysql 性能优化完全手册
涨姿势:Mysql 性能优化完全手册 深入理解MySQL服务器架构 客户端层 MySQL逻辑架构整体分为三层,最上层为客户端层,诸如:连接处理.授权认证.安全等功能均在这一层处理. 中间层 MySQL ...
- 再说项目 Dec 27th 2018
其实对于任何项目来说,最难不是开发或者系统等技术的问题,反而是需求的问题,需求一直变,一直定不下来,导致流程变来变去,系统方案层面也确定不下来.而需求的问题,归根结底还是人的问题.项目的关键用户对现有 ...
- AD服务无法启动
转自网络资源:http://www.great-one.co.uk/archives/289 版本:win08 : 该方法支持hyper-v 虚拟机 启动报错: A Windows 2008 R2 D ...
- 使用shell进行etl数据验证
方法如下: 整理校验的类型,不同的类型配置文件不一样. 1:校验数据增量:需要设置表名,增量字段. 2:非法值校验:设置表名,条件,校验字段,合法值/非法值范围. 3:自定义校验:设置表名,校验名称, ...
- Virtualbox扩容C盘
oracle vm virtualbox虚拟机里面系统盘C盘容量不够,需要扩容,步骤如下: 1.使用命令更改当前虚拟机的文件大小 VBoxManage.exe modifyhd YOUR_HARD_D ...
- Nginx+Memcache+一致性hash算法 实现页面分布式缓存(转)
网站响应速度优化包括集群架构中很多方面的瓶颈因素,这里所说的将页面静态化.实现分布式高速缓存就是其中的一个很好的解决方案... 1)先来看看Nginx负载均衡 Nginx负载均衡依赖自带的 ngx_h ...
- chmod 755 是李鬼(转)
(1) 使用ls –l查看文件,前面显示的-rwxrwxr-x是什么意思? (2) chmod 755 xxx.sh又是什么意思? 1分钟简单说下,这两个和权限相关的问题. 先说下文件类型,访问方式, ...
- python中令人惊艳的小众数据科学库
Python是门很神奇的语言,历经时间和实践检验,受到开发者和数据科学家一致好评,目前已经是全世界发展最好的编程语言之一.简单易用,完整而庞大的第三方库生态圈,使得Python成为编程小白和高级工程师 ...