letcode 508 出现最多的子树元素和(递归)

6 篇文章 0 订阅

题目描述
给你一个二叉树的根结点,请你找出出现次数最多的子树元素和。一个结点的「子树元素和」定义为以该结点为根的二叉树上所有结点的元素之和(包括结点本身)。

你需要返回出现次数最多的子树元素和。如果有多个元素出现的次数相同,返回所有出现次数最多的子树元素和(不限顺序)。

示例 1:
输入:

5/  2   -3

返回 [2, -3, 4],所有的值均只出现一次,以任意顺序返回所有值。

示例 2:
输入:
5/  2   -5

返回 [2],只有 2 出现两次,-5 只出现 1 次。
解题思路:
首先此题需要遍历二叉树,因此先考虑递归,然后在遍历过程中将需要的操作添加进去。难点在于如何写递归函数,首先先思考递归函数的参数,TreeNode是必要的,其次我们要将遍历中的元素和和出现的次数对应的保存起来,一定需要一个map,因为我们要将每个子树的元素和求出来,那返回值需要设置为int,题目已经规定数据的大小,所以不需要考虑测试数据的范围。其次考虑递归函数的结束条件,当遍历到root为null时,返回0;然后我们要将所有子树的元素和求出来,必然要从下向上求和,所以先遍历再进行操作,当前节点的子树的元素和就等于当前节点的值加上其子树的值,求出对应的值后,再将求得的值作为key加入到map中去,对应的value默认值为0,每次加入一个key就将其value加一,每次加入再将max的值更新一次(max为出现次数最多的子树元素出现的次数)。在递归完成后,每个子树元素和以及其对应出现的次数就存入到map中了,然后我们遍历这个map,将所有出现次数为max的key加入到list中去,因为题目要求返回int[] 类型,因此还要将list转换为int[]返回。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private int max = 0; //max定义为类变量,方便找出最大值
    public int reverse(TreeNode root , Map<Integer,Integer> temp){
        if(root == null) return 0;
        int left = reverse(root.left , temp);
        int right = reverse(root.right , temp); //先遍历左右子树,走到最下面,从下往上计算每个子树的元素和。
        int val = left+right+root.val; //当前节点的子树元素和等于左右子树加上当前元素
        temp.put(val,temp.getOrDefault(val,0)+1); //当前元素和出现过的话就用当前元素对应的出现次数,未出现过就设置           //默认值为1并加一
        max = Math.max(max,temp.get(val)); //每次遍历一个树,都去更新max的值
        return val;
    }
    public int[] findFrequentTreeSum(TreeNode root) {
        if(root == null) return new int[0]; //如果树为空直接返回
        Map<Integer,Integer> temp  = new HashMap();
        reverse(root , temp);
        
        List<Integer> res = new LinkedList<>(); //用list先将结果集添加进去,然后再转入数组中返回
        for(Integer i : temp.keySet()){
            if(temp.get(i) == max)
                res.add(i);
        }
        int[] resArr = new int[res.size()];
        for(int i = 0;i < res.size();i++){
            resArr[i] = res.get(i);
        }
        return resArr;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值