[面试算法]Python根据前序+中序或后序+中序还原二叉树

导言在上一篇博客《[面试算法]Python实现二叉树三种遍历的递归与非递归形式》当中,我们详细讲述了二叉树深度优先遍历的各种办法。一道常见的面试题是,如何根据三种遍历的结果,还原出二叉树或进行二叉树重建?还是拿是上一篇博客的二叉树举例,二叉树的示意图及其三种遍历的结果都贴在下面:首先,根据某一种遍历的结果可以还原出二叉树吗?比如,仅仅有前序遍历的结果信息,我们知道A是二叉树的根节点,但是除此之外,就不知道了,比如下面这棵二叉树,其前序遍历的结果,和上面的二叉树前序遍历结果是一样的:因此,仅仅根据前
摘要由CSDN通过智能技术生成

导言

在上一篇博客《[面试算法]Python实现二叉树三种遍历的递归与非递归形式》当中,我们详细讨论了二叉树深度优先遍历的各种方式。一道常见的面试题是,如何根据三种遍历的结果,还原出二叉树,或者说进行二叉树重建?还是拿是上一篇博客的二叉树举例,二叉树的示意图及其三种遍历的结果都贴在下面:
在这里插入图片描述
首先,根据某一种遍历的结果可以还原出二叉树吗?比如,仅仅有前序遍历的结果,我们只能知道A是二叉树的根节点,但是除此之外,就什么也不知道,比如下面这棵二叉树,其前序遍历的结果,和上面的二叉树前序遍历结果是一样的:
在这里插入图片描述
因此,仅仅根据前序遍历的结果无法还原出唯一的二叉树。仅仅根据中序遍历的结果,我们什么都不知道,因为D B G E A C F可能对应这样一棵二叉树:D (B G E A C F),其中D是根节点,左子树为空,(B G E A C F)为右子树,这也满足上述中序遍历的结果。根据后序遍历,同样不能唯一还原出二叉树,根据后序遍历D G E B F C A我们只能知道:A是根节点,其他的什么都不知道。所以,我们至少需要两种遍历结果,才能进行二叉树重建。

如果有了前序遍历和后序遍历的结果,我们可以还原出唯一的二叉树吗?不能。

已知前序遍历结果A B D E G C F和后续遍历结果D G E B F C A,由此可知,A是根节点,那么去掉A之后分别是:B D E G C FD G E B F C,而这两个序列中,前者的第一个元素B不等于后者的最后一个元素C,说明这两个前序遍历和后序遍历,属于两棵子树,不属于一棵子树。

我们看一下:
前序:B D E G C F
后序:D G E B F C

可以肯定地是,B是一棵子树的根节点,C是另一棵子树的根节点。逐个扫描发现,B D E GD G E B应当属于一棵子树,因为这两个序列中:前者的首元素=后者的尾元素,符合前序和后序遍历的特点。类似地,C FF C属于同一棵子树。并且B D E G应当属于左子树,因为在前序遍历中,这个序列在C F的前面。看到这里,感觉有点希望可以将二叉树还原了,然而问题现在来了。

既然C FF C是根节点A的右子树的前序和中序遍历结果,那么这棵子树当中C一定是根节点,那么F节点是属于左子树还是右子树呢?如果F是右子树,那么左子树为空,符合前序和中序遍历结果,也和原二叉树相同。如果F属于左子树,也符合前序和中序遍历结果。至此,出现了不能唯一确定的问题,在B D E G C F当中也有类似的问题。

因此,根据前序+后序遍历结果无法重建二叉树。剩下只有两种可能:前序+中序、后序+中序,这两种都可以进行二叉树重建。

根据前序遍历+中序遍历还原二叉树

根据前序遍历结果A B D E G C F和中序遍历结果D B G E A C F可知,A是根节点,而中序遍历中,根节点可以分割左右子树,说明中序遍历当中,D B G E是左子树,C F是右子树。无论是什么遍历,某棵子树的节点个数总是相等的,因此根据左子树的中序遍历D B G E,可以分割出这棵子树的前序遍历结果为B D E G。右子树类似。

因此:
左子树的前序+中序结果为:B D E GD B G E
右子树的前序+中序的结果为:C FC F

剩下的事情,就是采用同样的方法了。

先来看左子树,根据前序遍历B D E G可知,B一定是根节点,放到中序遍历当中,可知分割的左右子树是DG E。因此,B的左子树对应着前序+中序结果为:DD,只有一个节点,左子树重建完成。B的右子树对应着前序+中序结果为:G EE G,有两个节点,类似地,可知G是根节点,E是左子树,右子树为空,重建完成。

对于右子树的前序+后序:C FC F,可知C是根节点,F属于右子树,右子树只有一个F节点,左子树为空,重建完成!

上述过程是递归的,因此可以采用递归程序完成。递归的方法是:

  1. 根据前序遍历确定根节点root,根据root在中序遍历当中的位置分割左右子树对应的中序遍历结果;
  2. 根据左右子树中序遍历中节点的个数这个信息,结合前序遍历,确定左右子树的前序遍历结果;
  3. 现在知道左子树的前序+中序,可以进行递归;也知道右子树的前序+中序,可以进行递归;
  4. 递归的边界:如果某棵子树的节点个数为0,这棵子树重建完成,其根节点就是空,触及递归边界。

根据前序遍历+中序遍历还原二叉树的Python代码如下:

# 全局变量记录遍历的结果
result = []


# 前序
def dfs_before(root):
    if root == None:  # 遇到None,说明不用继续搜索下去
        return
    result.append(root)
    dfs_before(root.left)
    dfs_before(root.right)


# 中序遍历
def dfs_middle(root):
    if root == None:
        return
    dfs_middle(root.left)
    result.append(root)
    dfs_middle(root.right)


# 后序遍历
def dfs_after(root):
    if root == None:
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值