508. Most Frequent Subtree Sum

本文介绍了一种算法,用于找出给定树中最频繁出现的子树之和。通过遍历树并记录每个子树的和及其出现次数,最终找出出现频率最高的子树之和。

题目

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.

Examples 1
Input:

  5
 /  \
2   -3
return [2, -3, 4], since all the values happen only once, return all of them in any order.

Examples 2
Input:

  5
 /  \
2   -5
return [2], since 2 happens twice, however -5 only occur once.

Note: You may assume the sum of values in any subtree is in the range of 32-bit signed integer.

分析

计算一棵树中的最大子树之和,首先想到对树进行遍历,同时保存下来每个节点的子树之和,即左子树之和+右子树之和+节点本身值,叶节点的子树之和等于节点本身的值,因为要计算出现的频率,所以需要保存子树之和与出现频率的键值对,一开始想要用优先级队列或者multimap,以出现频率为键自动排序,这样最后只需要获取最前面的即可,但是这样的坏处是在遍历的过程中需要频繁查找当前子树之和到底出现多少次,以便于增加频率,会带来很多查找和删除的开销(频率增加后删除之前的频率中保存的子树之和),所以换个思路,使用子树之和为键,频率为值,这样计算出来一个值,可以直接自增来得到频率,并且设定一个maxCount标识,代表当前最大的频率(无关值),最后只需遍历一次map,找到与最大频率相同的键即为所求最大频率的子树之和。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> findFrequentTreeSum(TreeNode* root) {
        map<int,int> count;//保存各子树之和的频率
        int maxCount=0;//保存最大的频率
        countSubtreeSum(root,count,maxCount);//计算子树之和的频率
        
        vector<int> res;
        for(auto i:count){//只取最大频率的子树之和保存
            if(i.second==maxCount)
                res.push_back(i.first);
        }
        
        return res;
    }
    
    int countSubtreeSum(TreeNode* root,map<int,int>& count,int& maxCount){
        if(root==NULL)
            return 0;
        
        int sum=root->val;
        sum+=countSubtreeSum(root->left,count,maxCount);
        sum+=countSubtreeSum(root->right,count,maxCount);//计算子树之和
        
        count[sum]++;//频率自增,如果之前没有,则会自动添加
        maxCount=max(maxCount,count[sum]);//当前子树之和频率增加后与最大频率比较,重置最大频率的值
        
        return sum;//返回子树之和
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值