[leetcode]508. Most Frequent Subtree Sum(Python)

[leetcode]508. Most Frequent Subtree Sum

    • 题目描述
    • 题目理解
    • 解题思路
      • 后序遍历+递归
      • MyMethod
    • Time

题目描述

Category:Medium Tree

Given the root of a tree, you are asked to find the most frequent subtree sum. 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). So what is the most frequent subtree sum value? If there is a tie, return all the values with the highest frequency in any order.
[leetcode]508. Most Frequent Subtree Sum(Python)_第1张图片

题目理解

给定一棵二叉树,查找最频繁出现的子树和。
节点的子树和定义为以该子节点为根的树的所有节点值之和。
最频繁出现定义为出现次数最多的树,若存在多个,以任意顺序输出即可。

解题思路

后序遍历+递归

使用递归实现后序遍历,并修改节点的值为该节点的子树和,并使用dict保存每个节点的子树和,最后遍历得到出现次数最多的子节点和。
思路借鉴:https://www.jianshu.com/p/c861361dc20f

class Solution:
    # Runtime: 48ms 71.47%  MemoryUsage: 15.6MB 100.00%
    def findFrequentTreeSum2(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        self.counter = collections.Counter()
        self.postOrderTraversal(root)
        maxValue = max(self.counter.values())
        return [key for key in self.counter.keys() if self.counter[key] == maxValue]

    def postOrderTraversal(self, node):
        if node.left:
            node.val += self.postOrderTraversal(node.left)
        if node.right:
            node.val += self.postOrderTraversal(node.right)
        self.counter[node.val] += 1
        return node.val

和我的实现思路差不多,学习修改节点值的思路(好像只能采用后序遍历)。但修改节点值减少空间占用,不适用于不可修改原树的情况。

:补充collections模块 – Counter
collections是Python内建的一个集合模块,提供了许多有用的集合类。
Counter是一个简单的计数器,例如,统计字符出现的个数:

>>> from collections import Counter
>>> c = Counter()
>>> for ch in 'programming':
...     c[ch] = c[ch] + 1
...
>>> c
Counter({'g': 2, 'm': 2, 'r': 2, 'a': 1, 'i': 1, 'o': 1, 'n': 1, 'p': 1})

Counter实际上也是dict的一个子类,上面的结果可以看出,字符’g’、‘m’、'r’各出现了两次,其他字符各出现了一次。
该部分来自:廖雪峰老师的教程
疑问:或许Counter用作字典计数时可以按照出现次数排序?

from collections import Counter
string = 'abdiejmcodfjsljdli jiejwi ppsjijds klndjknajbd jsjzljij fijpfwe fzsdzssds'
list1 = [1,1,1,1,1,1,2,3,4,4,5,1,2,9,3,4,6]
one_list=[56,7,4,23,56,9,0,56,12,3,56,34,45,5,6,56]

c = Counter()
num_counter1 = Counter()
num_counter2 = Counter()

for ch in string:
    c[ch] = c[ch] + 1

for num in list1:
    num_counter1[num] += 1

for num in one_list:
    num_counter2[num] += 1

print(c)
print(num_counter1)
print(num_counter2)

输出如下所示:

Counter({'j': 14, 'd': 8, 's': 8, 'i': 7, ' ': 6, 'l': 4, 'f': 4, 'p': 3, 'z': 3, 'e': 3, 'w': 2, 'b': 2, 'k': 2, 'a': 2, 'n': 2, 'c': 1, 'o': 1, 'm': 1})
Counter({1: 7, 4: 3, 2: 2, 3: 2, 5: 1, 6: 1, 9: 1})
Counter({56: 5, 0: 1, 34: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 9: 1, 12: 1, 45: 1, 23: 1})

检索发现还有一个博主,发现collections-Counter可以不改变原有顺序有序生成元素的计数字典,考虑可以通过此来获取list的有序去重复。部分例子参考了他的,贴个地址
未发现有关官方文件具体说明,该点存疑。

MyMethod

SubtreeSum函数使用递归的思想,返回每个节点的子树和,并使用字典进行记录。
主函数中借助字典和max函数得到最频繁出现的次数,依次遍历字典中各个子树和出现的次数,用res记录最频繁出现的子树和,输出即可。

class Solution:
    # Runtime: 48ms 71.47%  MemoryUsage: 16.1MB 100.00%
    def findFrequentTreeSum(self, root: TreeNode) -> List[int]:
        if root is None:
            return
        res = {}
        result_list = []
        self.SubtreeSum(root, res)
        max_num = max(res.values())
        for k, v in res.items():
            if v == max_num:
                result_list.append(k)
        return result_list

    def SubtreeSum(self, root, res):
        if root is None:
            return 0
        left = self.SubtreeSum(root.left, res)
        right = self.SubtreeSum(root.right, res)
        subsum = left + right + root.val
        if subsum in res:
            res[subsum] += 1
        else:
            res[subsum] = 1
        return subsum

Time

2020.3.20 丧丧的早上 要加油呀!!!

你可能感兴趣的:(leetcode)