数据结构与算法12、剑指Offer5、6-重建二叉树、树的子结构

树用递归比较多,每次都要选择left子树、right子树,所以用循环不太方便,直接递归选择子树作为当前树来进行处理。

前序、中序、后序遍历

直接看链接

前序:根、左、右递归
中序:左、根、右递归
后续:左、右、根递归

在这里插入图片描述
分析:
前序的第一个元素必定是根节点,那么中序整体结构是左根右,
所以前序的第一个元素在中序中的位置的左边为左子树,右边为右子树。
首先整体前、中序看做一个树进行处理,然后找到左、右子树后,再递归对左、右子树进行处理。
那么递归结束的条件?前/中序序列中没有剩余数据了即返回None。
边界条件也进行判断一下?序列为空则返回None。

递归函数的作用从整体和局部两个方面分三步走:
1.整体:确定当前root节点,然后root的left和right想要被确定函数就必须要返回一个东西。
2.局部:假设现在是子树,root节点被确定后,该root节点的left和right被确定可以先不理会,那么整个函数返回的应该是该子树的root节点。
3.整体+局部:先确定最终的root节点,然后root.left得到的就是左子树返回的‘root’,root.right同理,最后返回最终的root即可。

递归的三套路和DP一样,也是找到函数作用,找到关联处,找到停止条件。

直接上代码:

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        # write code here
        if len(pre) == 0:
            return None
        
        root = TreeNode(pre[0])
        mid = tin.index(pre[0])
        root.left = self.reConstructBinaryTree(pre[1:mid+1], tin[:mid])
        root.right = self.reConstructBinaryTree(pre[mid+1:], tin[mid+1:])
        return root

在这里插入图片描述
分析:
复杂问题分解为几个简单的问题。

A树大一点,B树小一点,将B树拿着在A树里找,有匹配到的,则B是A的子结构。
那么可以拆分为两个问题,一个问题是将B树与A树中的每个子树进行判断是否子结构另一个问题是如何进行判断是否是子结构。注意第二个问题是A子树和B树均从根节点开始一步步进行判断

1.那么我们先考虑A子树和B树从根节点进行判断的方法:
先判断根节点,然后判断左子树,再判断右子树,那么用循环不好表示左、右子树,所以还是用递归去实现。

def isSubtree(self, roota, rootb):
	if rootb is None:  # B树都结束了,但A树还有,那么B是A的子结构
	    return True
	if roota is None:  # A提前结束了,肯定不是子结构了。
	    return False
	
	if roota.val != rootb.val:
	    return False
	left = isSubtree(roota.left, rootb.left)
	if left is False:
	    return False
	right = isSubtree(roota.right, rootb.right)
	if right is False:
	    return False
	return True

2.再考虑将B树与A树中的每个子树进行判断是否子结构:
同样用到递归。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def HasSubtree(self, pRoot1, pRoot2):
        # write code here
        if pRoot1 is None:
            return False
        if pRoot2 is None:
            return False
        
        if self.isSubtree(pRoot1, pRoot2):
            return True
        left = self.HasSubtree(pRoot1.left, pRoot2)
        # 注意这里千万不要写成isSubtree函数!!!
        if left is True:
        # 注意这里的True判断,如果为False,
        # 那么则继续向下判断,而不是return False!!!
        # 所以这里是判断True!
            return True
        right = self.HasSubtree(pRoot1.right, pRoot2)
        if right is True:
            return True
        #return False
        
    def isSubtree(self, roota, rootb):  # 该部分注释参考上面写好的注释
        if rootb is None:
            return True
        if roota is None:
            return False

        if roota.val != rootb.val:
            return False
        left = self.isSubtree(roota.left, rootb.left)
        if left is False:
            return False
        right = self.isSubtree(roota.right, rootb.right)
        if right is False:
            return False
        return True
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xu_Wave

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值