Given the root
of a binary tree, return the most frequent subtree sum. If there is a tie, return all the values with the highest frequency in any order.
The subtree sum of a node is defined as the sum of all the node values formed by the subtree rooted at that node (including the node itself).
Example 1:
Input: root = [5,2,-3] Output: [2,-3,4]
Example 2:
Input: root = [5,2,-5] Output: [2]
Constraints:
- The number of nodes in the tree is in the range
[1, 104]
. -105 <= Node.val <= 105
一棵二叉树,以它的每一个节点为根节点构成一棵棵子树,每棵子树的所有节点值的和叫做子树和,不同子树的子树和有可能相同,现在要求找出出现频率最高的所有子树和。
暴力解法就是以每个节点为根节点求出它们对应子树的和,同时统计每个子树和出现的次数,从而找出出现次数最多的所有子树和。然而,如果每次都重复计算每棵子树的和,将耗费太多时间做重复计算。我们知道,对于一个节点,如果知道了其左右子树的和,那么以它为根节点的子树和就是它本身的节点值加上其左右子树和。而对于叶节点对应的子树和也就是它们自己。因此我们可以只用一次后序遍历(Postorder Traversal)从底向上就可算出所有子树的子树和。在遍历时用一个dict记录各个和出现的次数,同时更新最高频率值,这样遍历完就知道最高频率,然后从dict中找出对应的和。
class Solution:
def findFrequentTreeSum(self, root: Optional[TreeNode]) -> List[int]:
freq = collections.defaultdict(int)
maxFreq = 0
def helper(node):
if not node:
return 0
nonlocal freq, maxFreq
lsum = helper(node.left)
rsum = helper(node.right)
tsum = node.val + lsum + rsum
freq[tsum] += 1
maxFreq = max(freq[tsum], maxFreq)
return tsum
helper(root)
res = []
for k, v in freq.items():
if v == maxFreq:
res.append(k)
return res