零 標題:演算法(leetcode,附思維導圖 + 全部解法)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://leetcode.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 博主簡介
碼農三少 ,一個致力於編寫 極簡、但齊全題解(演算法) 的博主。
專注於 一題多解、結構化思維 ,歡迎一起刷穿 LeetCode ~