leetcode 508: 出现次数最多的子树元素和 刷题 打天下 思路+注释

leetcode 508:出现次数最多的子树元素和

题目描述

给出二叉树的根,找出出现次数最多的子树元素和。一个结点的子树元素和定义为以该结点为根的二叉树上所有结点的元素之和(包括结点本身)。然后求出出现次数最多的子树元素和。如果有多个元素出现的次数相同,返回所有出现次数最多的元素(不限顺序)。

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)
链接:https://leetcode-cn.com/problems/most-frequent-subtree-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的解法

首先想到的就是,先用一个递归函数用于计算子树的元素和。之后再遍历所有节点,计算出所有子树元素和结果。因为需要记录元素和出现的次数以及最后返回次数最多的元素和,所以考虑用一个字典存储。

代码如下:

from collections import defaultdict
class Solution:
    def findFrequentTreeSum(self, root: TreeNode) -> List[int]:
        res = defaultdict(int)  # 默认值为 int型的0
        def helper(root):  # 递归函数 用于计算子树元素和
            if not root:  # 终止条件 如果根节点为空,则返回0
                return 0
            return root.val+helper(root.left)+helper(root.right)  # 否则返回 根节点+左子树和+右子树和
        if not root: 
            return []
        stack = [root]  # 这里开始 二叉树的前序遍历:根->左->右
        while stack:
            root = stack.pop()
            res[helper(root)] += 1  # 用一个字典存储出现的次数,这里注意使用 defaultdict。
            # defaultdict就是带有默认值的字典,遇到一个新的键的时候,不需要先声明,可以直接使用,那它对应的键值就是默认值。
            if root.right: stack.append(root.right)  # 因为是栈stack 先进后出,所以要先加入右节点,再加入左节点
            if root.left: stack.append(root.left)
        t = []   # 这里开始,找 次数最多的元素和
        for k in sorted(res,key=res.__getitem__,reverse=True):  # 按照键值对字典进行排序
            if t :
                if res[k] == res[t[-1]]: # 如果与第一名的次数相同
                    t.append(k)  # 继续添加
                else:
                    break
            else:
                t.append(k)  # 第一名出现了哟
        return t

运行结果:
运行结果
哇…这个耗时,绝了嘿!但是我自己写出来了,白菜不要对自己要求这么高,嗯,我真的很不错。
时间复杂度很高,之前也想到过,因为很多东西重复计算了。

其他方法

赶紧看看别人的解法诶,脑子转不动了啊

class Solution:
    def __init__(self):
        self.h = {}
        
    def _sum(self, rt):
        if not rt: return 0
        tmp = rt.val 
        tmp += self._sum(rt.left)
        tmp += self._sum(rt.right)
        self.h[tmp] = 1 if not self.h.get(tmp) else self.h[tmp] + 1
        return tmp
            
    def findFrequentTreeSum(self, root: TreeNode) -> List[int]:
        if not root: return []
        if root.left is None and root.right is None: return [root.val]
        #print(root)
        self._sum(rt=root)
        #print(self.h)
        hh = sorted(self.h.items(), key=lambda i: i[1], reverse=True)
        return [hh[i][0] for i in range(len(hh)) if hh[i][1] == hh[0][1]]

作者:Desgard_Duan
链接:https://leetcode-cn.com/problems/most-frequent-subtree-sum/solution/dfs-hash-ji-shu-by-desgard_duan/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
题解1

和我的思路其实一样!不过有一个地方(我怎么没想到,太蠢了),就是直接在 递归函数里存储次数。
因为计算整个二叉树的元素和的时候,就是会将每个节点对应的子树都计算一次,所以在这里就可以直接算次数了!

修改之后

from collections import defaultdict
class Solution:
    def findFrequentTreeSum(self, root: TreeNode) -> List[int]:
        global res  # 声明全局变量
        res = defaultdict(int)  # 默认值为 int型的0
        def helper(root):  # 递归函数 用于计算子树元素和
            if not root:  # 终止条件 如果根节点为空,则返回0
                return 0
            out = root.val+helper(root.left)+helper(root.right)
            global res
            res[out] += 1
            return out  # 否则返回 根节点+左子树和+右子树和
        if not root: 
            return []
        helper(root)
        t = []   # 这里开始,找 次数最多的元素和
        for k in sorted(res,key=res.__getitem__,reverse=True):  # 按照键值对字典进行排序
            if t :
                if res[k] == res[t[-1]]: # 如果与第一名的次数相同
                    t.append(k)  # 继续添加
                else:
                    break
            else:
                t.append(k)  # 第一名出现了哟
        return t

修改后结果

哟呵,真好的结果啊,我真的真的真的真的真的很不错
下道题,再见~

发布了28 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/xxx_gt/article/details/103577162