508、出现次数最多的子树元素和|算法(附思维导图)300题
零 标题:算法(牛客网,附思维导图 + 全部解法)300题之(508)出现次数最多的子树元素和
一 题目描述


二 解法总览(思维导图)

三 全部解法
1 方案1
1)代码:
// 方案1 “自己。后续遍历法”。
// 用时:14分钟。
// 思路:
// 1)状态初始化:resMap = new Map() 。
// 2)调用递归函数 updateRootValByDfs(root) 。
// 3)求得 出现次数最多的子树元素和 resMaxCount = getMaxCountByMap(resMap) 。
// 4)若 当前值(即 key )出现的次数 val 与 resMaxCount,
// 则 将 val 放入 resList 中。
// 5)返回结果 resList 。
var findFrequentTreeSum = function(root) {
    const updateRootValByDfs = (curRoot = null) => {
        // 1)递归出口
        if (!curRoot) {
            return;
        }
        const {left, right} = curRoot;
        if (!left && !right) {
            if (resMap.has(curRoot.val)) {
                resMap.set(curRoot.val, resMap.get(curRoot.val) + 1);
            }
            else {
                resMap.set(curRoot.val, 1);
            }
            return;
        }
        // 2)递归主体
        // 2.1)先更新 left 节点上的 val 。
        updateRootValByDfs(left);
        // 2.2)接着更新 right 节点上的 val 。
        updateRootValByDfs(right);
        // 2.3)最后更新 curRoot 节点上的 val 。
        if (left) {
            curRoot.val += (left.val);
        }
        if (right) {
            curRoot.val += (right.val);
        }
        if (resMap.has(curRoot.val)) {
            resMap.set(curRoot.val, resMap.get(curRoot.val) + 1);
        }
        else {
            resMap.set(curRoot.val, 1);
        }
    };
    const getMaxCountByMap = (map = new Map()) => {
        let resMaxCount = Number.NEGATIVE_INFINITY;
        for (const [key, val] of map) {
            resMaxCount = Math.max(resMaxCount, val);
        }
        return resMaxCount;
    };
    // 边界(根据提示,如下代码可忽略)
    if (!root) {
        return [];
    }
    // 1)状态初始化:resMap = new Map() 。
    let resMap = new Map();
    // 2)调用递归函数 updateRootValByDfs(root) 。
    updateRootValByDfs(root);
    // 3)求得 出现次数最多的子树元素和 resMaxCount = getMaxCountByMap(resMap) 。
    let resMaxCount = getMaxCountByMap(resMap),
        resList = [];
    // 4)若 当前值(即 key )出现的次数 val 与 resMaxCount,
    // 则 将 val 放入 resList 中。
    for (const [key, val] of resMap) {
        if (val === resMaxCount) {
            resList.push(key);
        }
    }
    // 5)返回结果 resList 。
    return resList;
}; 2 方案2
1)代码:
// 方案2 “官方。深度优先遍历法(本质:跟自己的方案1大体上是一样的)”。
// 参考:
// 1)https://牛客网.cn/problems/most-frequent-subtree-sum/solution/chu-xian-ci-shu-zui-duo-de-zi-shu-yuan-s-kdjc/
// 思路:
// 1)状态初始化:esMap = new Map(), resMaxCount = Number.NEGATIVE_INFINITY 。
// 2)调用递归函数 dfs(root) 。
// 3)若 当前值(即 key )出现的次数 val 与 resMaxCount,
// 则 将 val 放入 resList 中。
// 4)返回结果 resList 。
var findFrequentTreeSum = function(root) {
    const dfs = (curRoot = null) => {
        // 1)递归出口。
        if (!curRoot) {
            return 0;
        }
        // 2)递归主体。
        const {val, left, right} = curRoot,
            sum = val + dfs(left) + dfs(right);
        // 2.1)不断更新 resMap、resMaxCount 的值。
        resMap.set(sum, (resMap.get(sum) || 0) + 1);
        resMaxCount = Math.max(resMaxCount, resMap.get(sum));
        // 2.2)返回当前 sum 值!!
        return sum;
    };
    // 1)状态初始化:esMap = new Map(), resMaxCount = Number.NEGATIVE_INFINITY 。
    let resMap = new Map(),
        resMaxCount = Number.NEGATIVE_INFINITY;
    // 2)调用递归函数 dfs(root) 。
    dfs(root);
    // 3)若 当前值(即 key )出现的次数 val 与 resMaxCount,
    // 则 将 val 放入 resList 中。
    let resList = [];
    for (const [key, val] of resMap) {
        if (val === resMaxCount) {
            resList.push(key);
        }
    }
    // 4)返回结果 resList 。
    return resList;
}; 四 资源分享 & 更多
1 历史文章 - 总览

2 博主简介
码农三少 ,一个致力于编写 极简、但齐全题解(算法) 的博主。
专注于 一题多解、结构化思维 ,欢迎一起刷穿 牛客网 ~
 查看18道真题和解析
查看18道真题和解析

