- 从前序与中序遍历序列构造二叉树_leetcode105
- 从中序与后序遍历序列构造二叉树_leetcode106
- 根据前序和后序遍历构造二叉树_leetcode889
- 二叉树的序列化与反序列化_leetcode297
1.从前序与中序遍历序列构造二叉树
思路:
第一步:
前序遍历的第一个节点,即为根节点。
第二步:
由根节点,可以在中序遍历中,找到左子树对应的长度。
第三步:
根据左子树的长度,
可以在先序序列和中序序列中,找到左子树和右子树对应的先序序列和中序序列。
代码如下:
class
2.从中序和后序遍历序列构造二叉树
思路分析:
与上题类似,由后序遍历,来确定根节点的值。
然后,从中序遍历中,找到左右子树的长度及对应的序列,
递归构造即可。
代码如下:
class
3.从前序和后序遍历序列构造二叉树
思路1:根据前序和后序序列及起始位置来构建二叉树。
前序遍历的第一个节点可以确定根节点.
- 前序序列中,根节点的下一个节点,为左子树的根节点。
- 由前序序列中的根节点的值,可以在后序序列中,找到对应的根节点的位置,从而确定左子树的位置。
依次迭代,便可以递归构造出二叉树。
代码实现:
class
拓展:
仅仅知道前序遍历和后序遍历的顺序,不能唯一确定一棵二叉树。如下图所示:
二叉树遍历情况为
二叉树1的前序序列为
上述题解默认的是构造二叉树1的这种情况。由于leetcode中的测试用例是按照构建二叉树的层次遍历结构来验证,构造的结果,所以,上述代码能够通过。
思路二:leetcode官方题解,易于理解
前序遍历为:
(根结点) (前序遍历左分支) (前序遍历右分支)
而后序遍历为:
(后序遍历左分支) (后序遍历右分支) (根结点)
例如,如果最终的二叉树可以被序列化的表述为 [1, 2, 3, 4, 5, 6, 7],
那么其前序遍历为 [1] + [2, 4, 5] + [3, 6, 7],而后序遍历为 [4, 5, 2] + [6, 7, 3] + [1].
果我们知道左分支有多少个结点,我们就可以对这些数组进行分组,并用递归生成树的每个分支。
算法
我们令左分支有 L 个节点。我们知道左分支的头节点为 pre[1],但它也出现在左分支的后序表示的最后。
所以 pre[1] = post[L-1](因为结点的值具有唯一性),因此 L = post.indexOf(pre[1]) + 1。
现在在我们的递归步骤中,左分支由 pre[1 : L+1] 和 post[0 : L] 重新分支,
而右分支将由 pre[L+1 : N] 和 post[L : N-1] 重新分支。
这里,巧妙的利用数学中的设未知数,设有L个节点,使得编程变得简单。是上述思路一种的简化版。
代码实现如下:
class
4.二叉树的序列化和反序列化
思路:
序列化,就是层次遍历二叉树,将遍历结果用字符串来表示。若某一节点为null,则用特殊的字符来表示,如“#”
反序列化,根据层次化遍历序列,来重构二叉树。
代码实现:
public
结语
以上,便是关于二叉树与二叉树结构之间的四类题目总结。
从上面可知,有序列化的某一排序序列,可以反序列化,重构实际的二叉树。因为在序列化的过程中,是用了特殊的字符,来记录null节点的信息。
如果没有用特殊的符号来记录空信息,则需要通过两种方式的遍历序列,才能重构二叉树。
前序遍历+中序遍历,可以唯一确定一棵二叉树。
后序遍历+中序遍历,也可以唯一确定一棵二叉树。
但是,前序遍历+后序遍历,不能唯一确定一棵二叉树。