LeetCode 572.另一个树的子树
给定两个非空二叉树s和t,检验s中是否包含和t具有相同结构和节点值的字数。s的一个子树包括s的一个节点和这个节点的所有子孙。s也可以看做它自身的一颗子树。
实例1:
给定的树s:
3
/ \
4 5
/ \
1 2
给定的树t:
4
/ \
1 2
返回true,因为t与s的一个子树拥有相同的结构和节点值。
实例2:
给定的树s:
3
/ \
4 5
/ \
1 2
/
0
给定的树t:
4
/ \
1 2
返回false。
剑指Offer 26.树的子结构
输入两颗二叉树A,B,判断B是不是A的子结构。
说明:
约定空树不是任意一个树的子结构。
题目解读
这两个题有相似之处,因此把他们放在一起来讨论。
两道题的区别在于:前者是判断是否为子树,要求节点和节点的子孙都一样,而后者是判断是否为子结构,即使子孙不一样也可以接受。
对于前者来说,我们只需要遍历树的节点,然后判断当前节点及节点的子孙是否与另一棵树即可。
代码解析
判断子树
class Solution:
# 定义函数判断两棵树是否相等
def isSameTree(self, p, q):
if not p and not q:
return True
if p and q and p.val == q.val:
return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
else:
return False
def isSubtree(self, s: TreeNode, t: TreeNode) -> bool:
if not s or not t:
return False
# 借助队列来实现树的层次遍历
queue = [s]
while queue:
temp = queue.pop(0)
# 访问每个节点,看当前节点及子孙是否满足要求
flag = self.isSameTree(temp, t)
if flag:
return True
else:
if temp.left:
queue.append(temp.left)
if temp.right:
queue.append(temp.right)
return False
判断树的子结构
class Solution:
# 定义判断是否为子结构的函数
def isSubTree(self,p, q):
#与子树判断的关键区别,q遍历完了,就不用再管后面了
if not q:
return True
if p and q and p.val == q.val:
return self.isSubTree(p.left,q.left) and self.isSubTree(p.right, q.right)
else:
return False
# 递归进行判断
def HasSubtree(self, pRoot1, pRoot2):
# write code here
if not pRoot1 or not pRoot2:
return False
# 注意这里,不需要对pRoot同步递归,容易写错
return self.isSubTree(pRoot1, pRoot2) or self.HasSubtree(pRoot1.left, pRoot2) or self.HasSubtree(pRoot1.right, pRoot2)
Attention:
注意第二题的最后一行self.HasSubtree(pRoot1.left, pRoot2)
这个地方容易错写成self.HasSubtree(pRoot1.left, pRoot2.left)或self.HasSubtree(pRoot1.right, pRoot2.right)。
实际上,我们每次都要拿完整的pRoot2去比较,因此不要对其进行同步地递归。