【剑指offer】JZ26 树的子结构

1 问题

输入两棵二叉树A,B,判断B是不是A的子结构。(我们约定空树不是任意一个树的子结构)
假如给定A为{8,8,7,9,2,#,#,#,#,4,7},B为{8,9,2},2个树的结构如下,可以看出B是A的子结构
在这里插入图片描述
数据范围: 0 <= A的节点个数 <= 10000 0 <= B的节点个数 <= 10000

示例1
输入:{8,8,7,9,2,#,#,#,#,4,7},{8,9,2}
返回值:true

示例2
输入:{1,2,3,4,5},{2,4}
返回值:true

示例3
输入:{1,2,3},{3,1}
返回值:false

2 答案

这题直接不会,第二颗树如何遍历不知道

官方解

  1. 两层前序遍历

既然是要找到A树中是否有B树这样子树,如果是有子树肯定是要遍历这个子树和B树,将两个的节点一一比较,但是这样的子树不一定就是A树根节点开始的,所以我们还要先找到子树可能出现的位置。

既然是可能的位置,那我们可以对A树的每个节点前序递归遍历,寻找是否有这样的子树,而寻找是否有子树的时候,我们就将A树与B树同步前序遍历,依次比较节点值。

  • step 1:因为空树不是任何树的子树,所以要先判断B树是否为空树。
  • step 2:当A树为空节点,但是B树还有节点的时候,不为子树,但是A树不为空节点,B树为空节点时可以是子树。
  • step 3:每次递归比较A树从当前节点开始,是否与B树完全一致,同步前序遍历。
  • step 4:A树自己再前序遍历进入子节点,当作子树起点再与B树同步遍历。
  • step 5:以上情况任意只要有一种即可。
class Solution:
    def recursion(self, root1: TreeNode, root2: TreeNode) -> bool:
        if root1 is None and root2 is not None:
            return False
        if root2 is None:
            return True
        return root1.val == root2.val and self.recursion(root1.left, root2.left) and self.recursion(root1.right, root2.right)

    def HasSubtree(self , pRoot1: TreeNode, pRoot2: TreeNode) -> bool:
        if pRoot2 is None:
            return False
        if pRoot1 is None and pRoot2 is not None:
            return False
        flag1 = self.recursion(pRoot1, pRoot2)
        flag2 = self.HasSubtree(pRoot1.left, pRoot2) # pRoot1左节点与根节点进行对比
        flag3 = self.HasSubtree(pRoot1.right, pRoot2) # pRoot1右节点与根节点进行对比
        return flag1 or flag2 or flag3
  1. 两层层次遍历

根据方法一,所以这道题的思路,无非就是在A树中遍历每个节点尝试找到那个子树,然后每次以该节点出发能不能将子树与B树完全匹配。能用前序遍历解决,我们也可以用层次遍历来解决。

首先对于A树层次遍历每一个节点,遇到一个与B树根节点相同的节点,我们就开始同步层次遍历比较以这个节点为根的树中是否出现了B树的全部节点。因为我们只考虑B树的所有节点是否在A树中全部出现,那我们就以B树为基,再进行一次层次遍历,A树从那个节点开始跟随B树一致进行层次遍历就行了,比较对应的每个点是否相同,或者B树是否有超出A树没有的节点。

  • step 1:先判断空树,空树不为子结构。
  • step 2:利用队列辅助,层次遍历第一棵树,每次检查遍历到的节点是否和第二棵树的根节点相同。
  • step 3:若是相同,可以以该节点为子树根节点,再次借助队列辅助,同步层次遍历这个子树与第二棵树,这个时候以第二棵树为基,只要找到第二棵树的全部节点,就算找到了子结构。
import queue
class Solution:
    def helper(self, root1: TreeNode, root2: TreeNode) -> bool:
        q1 = queue.Queue()
        q2 = queue.Queue()
        q1.put(root1)
        q2.put(root2)
        while not q2.empty():  # empty后有()
            node1 = q1.get()
            node2 = q2.get()
            if node1 is None or node1.val != node2.val:
                return False
            if node2.left:
                q1.put(node1.left)
                q2.put(node2.left)
            if node2.right:
                q1.put(node1.right)
                q2.put(node2.right)
        return True
        
    def HasSubtree(self , pRoot1: TreeNode, pRoot2: TreeNode) -> bool:
        if pRoot1 is None or pRoot2 is None:
            return False
        q = queue.Queue()
        q.put(pRoot1)
        while not q.empty():
            node = q.get()
            if node.val == pRoot2.val:
                if self.helper(node, pRoot2):
                    return True
            if node.left:
                q.put(node.left)
            if node.right:
                q.put(node.right)
        return False

https://www.nowcoder.com/share/jump/9318638301698514375090

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

LouHerGetUp

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

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

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

打赏作者

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

抵扣说明:

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

余额充值