[剑指Offer] 26_树的子结构

67 篇文章 0 订阅
42 篇文章 0 订阅

题目

输入两棵二叉树A和B,判断B是不是A的子结构。

例:

                A                      B
                8                      8
            /       \                /   \
           8         7              9     2
         /   \       
        9     2
            /   \
           4     7

A树中有一部分子树和B是一样的,因此B是A的子结构。


思路

  1. 在A树中搜索和B树的root的val一样的节点,并从该节点向下逐个比对,如果B树遍历比对完成则表示是子结构,否则返回重新寻找root,直到A树遍历完毕。
    1. 时间复杂度:O(nlogn),如果A树中除了最右节点其余全部节点都和B树的全部节点值相同,A、B一样高,将会T(n) = 2T(n/2) + O(n)
    2. 空间复杂度:O(logn)递归深度
  2. 将A、B树的前序遍历缓存成字符串,比对B是否是A的子串,相同则表示匹配。比较是否字串使用in关键词,应该是O(n)。的因为B的大小是固定的,只要截取固定长度的字符串比较他们的哈希值 O(1),比较n次即可。
    1. 时间复杂度:O(n)
    2. 空间复杂度:O(n)

代码

思路1:时间复杂度:O(nlogn),空间复杂度:O(logn)

def substrucure_in_tree(main, sub):
    """    
    :param main: Big Tree 
    :param sub: substructure
    :return: bool
    """

    def compare(main_tree_sub, sub):
        """        
        :param main_tree_sub: node
        :param sub: substructure_root
        :return: bool
        """
        if not sub:
            return True
        if not main_tree_sub:
            return False
        if sub.val == main_tree_sub.val:
            return compare(main_tree_sub.left, sub.left) and compare(main_tree_sub.right, sub.right)
        return False

    if not main:
        return False
    if main.val == sub.val and compare(main, sub):
        return True
    else:
        return substrucure_in_tree(main.left, sub) or substrucure_in_tree(main.right, sub)
    return

思路2:时间复杂度:O(n) ,空间复杂度:O(n)

def substrucure_in_tree_2(main, sub):
    def preorder(root):
        return (root.val, preorder(root.left), preorder(root.right)) if root else None
    return str(preorder(sub)) in str(preorder(main))

思考

思路2是在LeetCode上看到的解法,相当于用空间换时间了。很有意思,代码很简洁。从另一个角度看,思路1对于极端情况重复比较和计算了很多次,所以思路2相当于添加了缓存,也就是备忘录法解决公共子问题,也是dp思想中的一点运用吧。
相似的题目,但是此题要求子孙节点严格相等,而不是覆盖。

LeetCode 572. 另一个树的子树

题目

给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值