508-Most Frequent Subtree Sum

kevin聰發表於2018-05-03

Description

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.


問題描述

給定二叉樹的根節點, 找出最頻繁的子樹和。一個節點的子樹和定義為以此節點為根節點的子樹上所有節點之和(包括此節點) 。如果有重複次數的子樹和, 以任意順序將其返回。


問題分析

後序遍歷, 利用Map儲存子樹和對應的次數, 利用maxSum儲存當前最大的子樹和出現次數, 每次函式呼叫回到一個子樹的根節點時, 比較當前根節點子樹和次數與maxSum之間的關係, 進行更新


解法1

class Solution {
    private Map<Integer,Integer>map = new HashMap();
    private int maxSum = 0;

    public int[] findFrequentTreeSum(TreeNode root) {
        List<Integer>list = new ArrayList();
        if(root == null)    return new int[0];

        count(root);
        for(Map.Entry<Integer,Integer> entry : map.entrySet()){
            if(entry.getValue() == maxSum){
                list.add(entry.getKey());
            }
        }

        return list.stream().mapToInt(i -> i).toArray();
    }

    int count(TreeNode root){
       int left = root.left != null ? count(root.left) : 0;
       int right = root.right != null ? count(root.right) : 0;
       int sum = left + right + root.val;
       map.put(sum,map.getOrDefault(sum,0) + 1);
       maxSum = Math.max(map.get(sum),maxSum);
       return sum;
    }
}

解法2

class Solution {
    int max = 0;

    public int[] findFrequentTreeSum(TreeNode root) {
        //用來儲存最終結果
        List<Integer> list = new ArrayList();
        //用來儲存子樹和對應的次數
        HashMap<Integer, Integer> map = new HashMap();
        //後序遍歷, 填充list
        sum(root, list, map);
        //將list轉化為array
        int[] ret = new int[list.size()];
        for(int i = 0; i < ret.length; i++) ret[i] = list.get(i);

        return ret;
    }

    private int sum(TreeNode root, List<Integer> list, HashMap<Integer, Integer> map) {
        if(root == null) return 0;

        int sum = 0;
        //後序遍歷, 獲取當前根節點對應的子樹和
        sum = sum(root.left, list, map) + sum(root.right, list, map) + root.val;
        map.put(sum, map.getOrDefault(sum, 0) + 1);
        //將count與max進行比較, 更新max和list
        int count = map.get(sum);
        if(count > max){
            list.clear();
            max = count;
        }
        if(count == max) list.add(sum); 

        return sum;
    }
}