返回

508. 出现次数最多的子树元素和的多种写法

后端

  1. 出现次数最多的子树元素和

给出二叉树的根节点 root,返回 root 的每个结点的子树元素和的最大值。

示例:

输入:[1,2,3]
输出:[6,9,5]
输入:[5,2,-3]
输出:[10,5,2]

提示:

  • 给定的树中有 1 到 1000 个结点。
  • 每个结点的值介于 -1000 到 1000 之间。

链接: https://leetcode-cn.com/problems/most-frequent-subtree-sum/

1. 暴力求解

暴力求解法是计算每个子树的元素和,然后将这些元素和存储在一个列表中。最后,我们找出列表中出现次数最多的元素和,并将其作为结果返回。

Python 实现:

def findFrequentTreeSum(root):
    # 计算每个子树的元素和
    def dfs(root):
        if not root:
            return 0
        left = dfs(root.left)
        right = dfs(root.right)
        # 返回子树的元素和
        return root.val + left + right

    # 将子树的元素和存储在列表中
    sums = []
    def postorder(root):
        if not root:
            return
        postorder(root.left)
        postorder(root.right)
        # 将子树的元素和添加到列表中
        sums.append(dfs(root))

    # 计算出现次数最多的元素和
    postorder(root)
    counts = collections.Counter(sums)
    max_count = max(counts.values())
    return [sum for sum, count in counts.items() if count == max_count]

Java 实现:

class Solution {
    private Map<Integer, Integer> sumCountMap;
    private int maxCount;

    public int[] findFrequentTreeSum(TreeNode root) {
        sumCountMap = new HashMap<>();
        maxCount = 0;
        postorder(root);

        List<Integer> result = new ArrayList<>();
        for (Map.Entry<Integer, Integer> entry : sumCountMap.entrySet()) {
            if (entry.getValue() == maxCount) {
                result.add(entry.getKey());
            }
        }
        return result.stream().mapToInt(i -> i).toArray();
    }

    private int postorder(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftSum = postorder(root.left);
        int rightSum = postorder(root.right);
        int sum = leftSum + rightSum + root.val;

        int count = sumCountMap.getOrDefault(sum, 0) + 1;
        sumCountMap.put(sum, count);
        maxCount = Math.max(maxCount, count);
        return sum;
    }
}

C++ 实现:

class Solution {
private:
    unordered_map<int, int> sumCountMap;
    int maxCount;

public:
    vector<int> findFrequentTreeSum(TreeNode* root) {
        sumCountMap.clear();
        maxCount = 0;
        postorder(root);

        vector<int> result;
        for (auto& entry : sumCountMap) {
            if (entry.second == maxCount) {
                result.push_back(entry.first);
            }
        }
        return result;
    }

private:
    int postorder(TreeNode* root) {
        if (root == nullptr) {
            return 0;
        }
        int leftSum = postorder(root->left);
        int rightSum = postorder(root->right);
        int sum = leftSum + rightSum + root->val;

        int count = sumCountMap[sum] + 1;
        sumCountMap[sum] = count;
        maxCount = max(maxCount, count);
        return sum;
    }
};

2. 使用深度优先搜索的优化解法

使用深度优先搜索的优化解法可以避免重复计算子树的元素和。在深度优先搜索过程中,我们维护一个字典来存储每个子树的元素和及其出现的次数。当我们访问一个子树时,我们首先检查字典中是否已经存在该子树的元素和。如果存在,我们直接从字典中获取出现的次数并更新最大出现的次数。如果不存在,我们计算子树的元素和,将它添加到字典中,并更新最大出现的次数。

Python 实现:

def findFrequentTreeSum(root):
    # 计算每个子树的元素和
    def dfs(root):
        if not root:
            return 0
        left = dfs(root.left)
        right = dfs(root.right)
        # 返回子树的元素和
        return root.val + left + right

    # 存储子树的元素和及其出现的次数
    sums = {}
    # 最大出现的次数
    max_count = 0

    def postorder(root):
        if not root:
            return
        postorder(root.left)
        postorder(root.right)
        # 计算子树的元素和
        sum = dfs(root)
        # 更新出现的次数和最大出现的次数
        sums[sum] = sums.get(sum, 0) + 1
        max_count = max(max_count, sums[sum])

    postorder(root)

    # 返回出现次数最多的元素和
    return [sum for sum, count in sums.items() if count == max_count]

Java 实现:

class Solution {
    private Map<Integer, Integer> sumCountMap;
    private int maxCount;

    public int[] findFrequentTreeSum(TreeNode root) {
        sumCountMap = new HashMap<>();
        maxCount = 0;
        postorder(root);

        List<Integer> result = new ArrayList<>();
        for (Map.Entry<Integer, Integer> entry : sumCountMap.entrySet()) {
            if (entry.getValue() == maxCount) {
                result.add(entry.getKey());
            }
        }
        return result.stream().mapToInt(i -> i).toArray();
    }

    private int postorder(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftSum = postorder(root.left);
        int rightSum = postorder(root.right);
        int sum = leftSum + rightSum + root.val;

        int count = sumCountMap.getOrDefault(sum, 0) + 1;
        sumCountMap.put(sum, count);
        maxCount = Math.max(maxCount, count);
        return sum;
    }
}

C++ 实现:

class Solution {
private:
    unordered_map<int, int> sumCountMap;
    int maxCount;

public:
    vector<int> findFrequentTreeSum(TreeNode* root) {
        sumCountMap.clear();
        maxCount = 0;
        postorder(root);

        vector<int> result;
        for (auto& entry : sumCountMap) {
            if (entry.second == maxCount) {
                result.push_back(entry.first);
            }
        }
        return result;
    }

private:
    int postorder(TreeNode* root) {
        if (root == nullptr) {
            return 0;
        }
        int leftSum = postorder(root->left);
        int rightSum = postorder(root->right);
        int sum = leftSum + rightSum + root->val;

        int count = sumCountMap[sum] + 1;