时间:2020-9-10
题目地址:https://leetcode-cn.com/problems/find-duplicate-subtrees/
题目难度:Medium
题目描述:
给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。
两棵树重复是指它们具有相同的结构以及相同的结点值。
示例 1:
1
/ \
2 3
/ / \
4 2 4
/
4
下面是两个重复的子树:
2
/
4
和
4
思路1:设计键这块一开始没想清楚,其实就是存下 每个节点为根 子树的样子
代码段1:通过
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import defaultdict
class Solution:
def findDuplicateSubtrees(self, root: TreeNode) -> List[TreeNode]:
res = defaultdict(list)
def helper(root):
if not root: return ''
#print(root.val)
s = ' '.join((str(root.val), helper(root.left), helper(root.right)))
res[s].append(root)
return s
helper(root)
#print(res)
return [l[0] for l in res.values() if len(l) > 1]
总结:
-
defaultdict类的初始化函数接受一个类型作为参数,当所访问的键不存在的时候,可以实例化一个值作为默认值
>>> from collections import defaultdict>>> dd = defaultdict(list)
>>> dd
d
defaultdict(<type 'list'>, {}) -
关于如何设计键的建议。
当字符串 / 数组中每个元素的顺序不重要时,可以使用排序后的字符串 / 数组作为键。
如果只关心每个值的偏移量,通常是第一个值的偏移量,则可以使用偏移量作为键。(0, x1-x0, x2-x0,...)
在树中,你有时可能会希望使用 TreeNode 作为键。 但在大多数情况下,采用子树的序列化表述可能是一个更好的主意。
在矩阵中,你可能希望使用行索引或列索引作为键。
在数独中,可以将行索引和列索引组合来标识此元素属于哪个块。有时,在矩阵中,您可能希望将值聚合在同一对角线中。
-
遇到输出超出限制的,哈哈哈,认真点啊,还一直在看代码逻辑
-
今天教师节,在群里发了问候,加了张老师,静候十月份张老师来京,开心哇
2021-01-27
思路2:拆解思路
1、想清楚每个节点要干什么? 判断我的子树和别人有没有重复。
关键点一、我的子树长什么样子? 后续遍历,序列化二叉树即可
关键点二、其他子树长什么样子 把每次调用的结果保存下来
2、同一类的重复子树,你只需要返回其中任意一棵的根结点? 存一下次数
代码段2:通过
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def findDuplicateSubtrees(self, root: TreeNode) -> List[TreeNode]:
memo = defaultdict(int) # 保留以 每个节点为根的子树 及其出现次数
res = []
def subTree(root) -> TreeNode:
if root == None:
return '#'
left = subTree(root.left)
right = subTree(root.right)
sub_tree = left + ',' + right + ',' + f'{root.val}' # 以当前节点为根的子树长这样
if memo[sub_tree] == 1:
res.append(root)
memo[sub_tree] += 1
print(sub_tree)
return sub_tree
subTree(root)
return res
总结:
-
拆解问题的思路真的是畅快的,我的培养这种解决问题的思路。