Given the?root ?of a binary tree, return all?duplicate subtrees.
For each kind of duplicate subtrees, you only need to return the root node of any?one?of them.
Two trees are?duplicate?if they have the?same structure?with the?same node values.
Example 1:
Input: root = [1,2,3,4,null,2,4,null,null,4]
Output: [[2,4],[4]]
Example 2:
Input: root = [2,1,1]
Output: [[1]]
Example 3:
Input: root = [2,2,2,3,null,3,null]
Output: [[2,3],[3]]
Constraints:
- The number of the nodes in the tree will be in the range?
[1, 10^4] -200 <= Node.val <= 200
给定一棵二叉树,要求找出树中所有重复出现的子树(两个及其以上相同的子树),返回所有出现过重复的子树的节点。所谓相同子树是指树结构相同,所有相对应的节点值相等。
我们对于如何比较两棵二叉树是否相同比较熟悉,因此这道题的暴力解法是对所有值相同的节点,两两进行比较从而找出相同的子树。很显然这将耗费大量时间,因此需要找更优解法。
相同子树具有相同结构,如果能将树结构以某种形式保存下来,那么就可以通过统计相同结构(包括节点值相同)的子树出现的次数来确定哪些子树在树中重复出现过。我们之前刷过的一道题是关于二叉树和字符串之间相互转换的,因此这题同样也可以把任意一棵二叉子树以一个唯一的字符串来表示,这样就可以用一个字典集来存放具有相同字符串的子树根节点。当一个字符串对应的节点个数超过1个就表示该字符串对应的子树重复出现过。
对于如何将所有子树都转成对应的字符串结构,其实只要一次前序遍历就可以,从底向上构造字符串,每次在处理一个节点时,它的左右子树已经通过递归调用转成字符串了,因此只要把当前节点值转成字符串再与其左右子树字符串相连,中间通过空格或逗号分割开,这样就完成以当前节点为根节点的子树向字符串的转化。另外在递归遇到空节点时可以用一个特殊符号(如"#")来表示这样才能确保字符串唯一性。
class Solution:
def findDuplicateSubtrees(self, root: Optional[TreeNode]) -> List[Optional[TreeNode]]:
sub = {}
def dfs(node):
if not node:
return "#"
ret = str(node.val) + "," + dfs(node.left) + "," + dfs(node.right)
if ret in sub:
sub[ret].append(node)
else:
sub[ret] = [node]
return ret
dfs(root)
res = []
for s,nodes in sub.items():
if len(nodes) > 1:
res.append(nodes[0])
return res
|