原题
Given two non-empty binary trees s and t, check whether tree t has exactly the same structure and node values with a subtree of s. A subtree of s is a tree consists of a node in s and all of this node’s descendants. The tree s could also be considered as a subtree of itself.
Example 1:
Given tree s:
3
/ \
4 5
/ \
1 2
Given tree t:
4
/ \
1 2
Return true, because t has the same structure and node values with a subtree of s.
Example 2:
Given tree s:
3
/ \
4 5
/ \
1 2
/
0
Given tree t:
4
/ \
1 2
Return false.
Reference Answer
Method one: DFS + DFS
容易想到,要判断一个树是不是另外一个树的子树,那么可以通过判断和这个数的任意子树是否相等的方式来做。那么就和100. Same Tree挺像了。所以这个题的做法就是在判断两棵树是否相等的基础上,添加上任意子树是否相等的判断。
任意子树是否相等判断的方式是:
- 当前两棵树是否相等
- s的左孩子和t是否相等
- t的左孩子和t是否相等
这三个条件是 或 的关系。
注意,判断两个数是否相等是与的关系。
判断是否是子树与是否是相同的树的代码简直是对称美啊~
这里很值得注意的一个地方时,无论是方法一还是方法二,都用了如下代码先从树结构进行判定:
if not s and not t:
return True
if not s or not t:
return False
其依据是“在当节点为空的时候给一个“#”表示,这样就能表示出不同的子树,因此只需要遍历一次就能得到结果。每次遍历到树的结尾的时候能够按照#区分,另外每个树的节点值之间用","分割。”
Code
class Solution:
def isSubtree(self, s, t):
"""
:type s: TreeNode
:type t: TreeNode
:rtype: bool
"""
# 1. method one: DFS + DFS
if not s and not t:
return True
if not s or not t:
return False
return self.isSameTree(s,t) or self.isSubtree(s.left, t) or self.isSubtree(s.right, t)
def isSameTree(self, s, t):
if not s and not t:
return True
if not s or not t:
return False
return s.val == t.val and self.isSameTree(s.left, t.left) and self.isSameTree(s.right, t.right)
Method Two: BFS + DFS
因为s的每个节点都可能成为和t相等的根节点,那么我们使用BFS来遍历每个节点,然后对每个节点进行判断就好了。
参考答案采用了
colletions.deque()
暂存节点,这种方式比采用list
更巧妙,先进先出也完全符合程序设定。
class Solution:
def isSubtree(self, s, t):
"""
:type s: TreeNode
:type t: TreeNode
:rtype: bool
"""
# 2. method two: BFS + DFS
if not s and not t:
return True
if not s or not t:
return False
que = collections.deque()
que.append(s)
while que:
node = que.popleft()
if not node:
continue
if self.isSameTree(node, t):
return True
que.append(node.left)
que.append(node.right)
return False
def isSameTree(self, s, t):
if not s and not t:
return True
if not s or not t:
return False
return s.val == t.val and self.isSameTree(s.left, t.left) and self.isSameTree(s.right, t.right)
Note
- 自己尝试着用后续遍历进行判定,存储两棵树节点值,进行判定的依据是认为是子树结构必然存储在后续遍历开始,没通过的原因正是在于该依据有错误,当树结构比较深时,其子结构可能存在中间,这时候子树结构无法对应原树结构的开始节点位置。
参考文献
[1] https://blog.csdn.net/fuxuemingzhu/article/details/71440802