diff --git a/solution/0500-0599/0508.Most Frequent Subtree Sum/README.md b/solution/0500-0599/0508.Most Frequent Subtree Sum/README.md index 9647cf651c26b..e7ef989303707 100644 --- a/solution/0500-0599/0508.Most Frequent Subtree Sum/README.md +++ b/solution/0500-0599/0508.Most Frequent Subtree Sum/README.md @@ -58,7 +58,13 @@ tags: -### 方法一 +### 方法一:哈希表 + DFS + +我们可以使用一个哈希表 $\textit{cnt}$ 记录每个子树元素和出现的次数,然后使用深度优先搜索遍历整棵树,统计每个子树的元素和,并更新 $\textit{cnt}$。 + +最后,我们遍历 $\textit{cnt}$,找到所有出现次数最多的子树元素和。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树的节点个数。 @@ -72,19 +78,19 @@ tags: # self.left = left # self.right = right class Solution: - def findFrequentTreeSum(self, root: TreeNode) -> List[int]: - def dfs(root): + def findFrequentTreeSum(self, root: Optional[TreeNode]) -> List[int]: + def dfs(root: Optional[TreeNode]) -> int: if root is None: return 0 - left, right = dfs(root.left), dfs(root.right) - s = root.val + left + right - counter[s] += 1 + l, r = dfs(root.left), dfs(root.right) + s = l + r + root.val + cnt[s] += 1 return s - counter = Counter() + cnt = Counter() dfs(root) - mx = max(counter.values()) - return [k for k, v in counter.items() if v == mx] + mx = max(cnt.values()) + return [k for k, v in cnt.items() if v == mx] ``` #### Java @@ -106,24 +112,18 @@ class Solution: * } */ class Solution { - private Map counter; + private Map cnt = new HashMap<>(); private int mx; public int[] findFrequentTreeSum(TreeNode root) { - counter = new HashMap<>(); - mx = Integer.MIN_VALUE; dfs(root); - List res = new ArrayList<>(); - for (Map.Entry entry : counter.entrySet()) { - if (entry.getValue() == mx) { - res.add(entry.getKey()); + List ans = new ArrayList<>(); + for (var e : cnt.entrySet()) { + if (e.getValue() == mx) { + ans.add(e.getKey()); } } - int[] ans = new int[res.size()]; - for (int i = 0; i < res.size(); ++i) { - ans[i] = res.get(i); - } - return ans; + return ans.stream().mapToInt(i -> i).toArray(); } private int dfs(TreeNode root) { @@ -131,8 +131,7 @@ class Solution { return 0; } int s = root.val + dfs(root.left) + dfs(root.right); - counter.put(s, counter.getOrDefault(s, 0) + 1); - mx = Math.max(mx, counter.get(s)); + mx = Math.max(mx, cnt.merge(s, 1, Integer::sum)); return s; } } @@ -154,26 +153,26 @@ class Solution { */ class Solution { public: - unordered_map counter; - int mx = 0; - vector findFrequentTreeSum(TreeNode* root) { - mx = INT_MIN; + unordered_map cnt; + int mx = 0; + function dfs = [&](TreeNode* root) -> int { + if (!root) { + return 0; + } + int s = root->val + dfs(root->left) + dfs(root->right); + mx = max(mx, ++cnt[s]); + return s; + }; dfs(root); vector ans; - for (auto& entry : counter) - if (entry.second == mx) - ans.push_back(entry.first); + for (const auto& [k, v] : cnt) { + if (v == mx) { + ans.push_back(k); + } + } return ans; } - - int dfs(TreeNode* root) { - if (!root) return 0; - int s = root->val + dfs(root->left) + dfs(root->right); - ++counter[s]; - mx = max(mx, counter[s]); - return s; - } }; ``` @@ -188,29 +187,26 @@ public: * Right *TreeNode * } */ -func findFrequentTreeSum(root *TreeNode) []int { - counter := make(map[int]int) - mx := 0 - var dfs func(root *TreeNode) int +func findFrequentTreeSum(root *TreeNode) (ans []int) { + cnt := map[int]int{} + var mx int + var dfs func(*TreeNode) int dfs = func(root *TreeNode) int { if root == nil { return 0 } s := root.Val + dfs(root.Left) + dfs(root.Right) - counter[s]++ - if mx < counter[s] { - mx = counter[s] - } + cnt[s]++ + mx = max(mx, cnt[s]) return s } dfs(root) - var ans []int - for k, v := range counter { + for k, v := range cnt { if v == mx { ans = append(ans, k) } } - return ans + return } ``` @@ -232,26 +228,22 @@ func findFrequentTreeSum(root *TreeNode) []int { */ function findFrequentTreeSum(root: TreeNode | null): number[] { - const map = new Map(); - let max = 0; - const dfs = (root: TreeNode | null) => { - if (root == null) { + const cnt = new Map(); + let mx = 0; + const dfs = (root: TreeNode | null): number => { + if (!root) { return 0; } const { val, left, right } = root; - const sum = val + dfs(left) + dfs(right); - map.set(sum, (map.get(sum) ?? 0) + 1); - max = Math.max(max, map.get(sum)); - return sum; + const s = val + dfs(left) + dfs(right); + cnt.set(s, (cnt.get(s) ?? 0) + 1); + mx = Math.max(mx, cnt.get(s)!); + return s; }; dfs(root); - const res = []; - for (const [k, v] of map) { - if (v === max) { - res.push(k); - } - } - return res; + return Array.from(cnt.entries()) + .filter(([_, c]) => c === mx) + .map(([s, _]) => s); } ``` @@ -279,33 +271,29 @@ function findFrequentTreeSum(root: TreeNode | null): number[] { use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; -impl Solution { - fn dfs( - root: &Option>>, - map: &mut HashMap, - max: &mut i32, - ) -> i32 { - if root.is_none() { - return 0; - } - let node = root.as_ref().unwrap().borrow(); - let sum = node.val + Self::dfs(&node.left, map, max) + Self::dfs(&node.right, map, max); - map.insert(sum, map.get(&sum).unwrap_or(&0) + 1); - *max = (*max).max(map[&sum]); - sum - } +impl Solution { pub fn find_frequent_tree_sum(root: Option>>) -> Vec { - let mut map = HashMap::new(); - let mut max = 0; - let mut res = Vec::new(); - Self::dfs(&root, &mut map, &mut max); - for (k, v) in map.into_iter() { - if v == max { - res.push(k); + fn dfs(root: Option>>, cnt: &mut HashMap) -> i32 { + if let Some(node) = root { + let l = dfs(node.borrow().left.clone(), cnt); + let r = dfs(node.borrow().right.clone(), cnt); + let s = l + r + node.borrow().val; + *cnt.entry(s).or_insert(0) += 1; + s + } else { + 0 } } - res + + let mut cnt = HashMap::new(); + dfs(root, &mut cnt); + + let mx = cnt.values().cloned().max().unwrap_or(0); + cnt.into_iter() + .filter(|&(_, v)| v == mx) + .map(|(k, _)| k) + .collect() } } ``` diff --git a/solution/0500-0599/0508.Most Frequent Subtree Sum/README_EN.md b/solution/0500-0599/0508.Most Frequent Subtree Sum/README_EN.md index 1e4ac92117882..d86b2e196e39f 100644 --- a/solution/0500-0599/0508.Most Frequent Subtree Sum/README_EN.md +++ b/solution/0500-0599/0508.Most Frequent Subtree Sum/README_EN.md @@ -52,7 +52,13 @@ tags: -### Solution 1 +### Solution 1: Hash Table + DFS + +We can use a hash table $\textit{cnt}$ to record the frequency of each subtree sum. Then, we use depth-first search (DFS) to traverse the entire tree, calculate the sum of elements for each subtree, and update $\textit{cnt}$. + +Finally, we traverse $\textit{cnt}$ to find all subtree sums that appear most frequently. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. @@ -66,19 +72,19 @@ tags: # self.left = left # self.right = right class Solution: - def findFrequentTreeSum(self, root: TreeNode) -> List[int]: - def dfs(root): + def findFrequentTreeSum(self, root: Optional[TreeNode]) -> List[int]: + def dfs(root: Optional[TreeNode]) -> int: if root is None: return 0 - left, right = dfs(root.left), dfs(root.right) - s = root.val + left + right - counter[s] += 1 + l, r = dfs(root.left), dfs(root.right) + s = l + r + root.val + cnt[s] += 1 return s - counter = Counter() + cnt = Counter() dfs(root) - mx = max(counter.values()) - return [k for k, v in counter.items() if v == mx] + mx = max(cnt.values()) + return [k for k, v in cnt.items() if v == mx] ``` #### Java @@ -100,24 +106,18 @@ class Solution: * } */ class Solution { - private Map counter; + private Map cnt = new HashMap<>(); private int mx; public int[] findFrequentTreeSum(TreeNode root) { - counter = new HashMap<>(); - mx = Integer.MIN_VALUE; dfs(root); - List res = new ArrayList<>(); - for (Map.Entry entry : counter.entrySet()) { - if (entry.getValue() == mx) { - res.add(entry.getKey()); + List ans = new ArrayList<>(); + for (var e : cnt.entrySet()) { + if (e.getValue() == mx) { + ans.add(e.getKey()); } } - int[] ans = new int[res.size()]; - for (int i = 0; i < res.size(); ++i) { - ans[i] = res.get(i); - } - return ans; + return ans.stream().mapToInt(i -> i).toArray(); } private int dfs(TreeNode root) { @@ -125,8 +125,7 @@ class Solution { return 0; } int s = root.val + dfs(root.left) + dfs(root.right); - counter.put(s, counter.getOrDefault(s, 0) + 1); - mx = Math.max(mx, counter.get(s)); + mx = Math.max(mx, cnt.merge(s, 1, Integer::sum)); return s; } } @@ -148,26 +147,26 @@ class Solution { */ class Solution { public: - unordered_map counter; - int mx = 0; - vector findFrequentTreeSum(TreeNode* root) { - mx = INT_MIN; + unordered_map cnt; + int mx = 0; + function dfs = [&](TreeNode* root) -> int { + if (!root) { + return 0; + } + int s = root->val + dfs(root->left) + dfs(root->right); + mx = max(mx, ++cnt[s]); + return s; + }; dfs(root); vector ans; - for (auto& entry : counter) - if (entry.second == mx) - ans.push_back(entry.first); + for (const auto& [k, v] : cnt) { + if (v == mx) { + ans.push_back(k); + } + } return ans; } - - int dfs(TreeNode* root) { - if (!root) return 0; - int s = root->val + dfs(root->left) + dfs(root->right); - ++counter[s]; - mx = max(mx, counter[s]); - return s; - } }; ``` @@ -182,29 +181,26 @@ public: * Right *TreeNode * } */ -func findFrequentTreeSum(root *TreeNode) []int { - counter := make(map[int]int) - mx := 0 - var dfs func(root *TreeNode) int +func findFrequentTreeSum(root *TreeNode) (ans []int) { + cnt := map[int]int{} + var mx int + var dfs func(*TreeNode) int dfs = func(root *TreeNode) int { if root == nil { return 0 } s := root.Val + dfs(root.Left) + dfs(root.Right) - counter[s]++ - if mx < counter[s] { - mx = counter[s] - } + cnt[s]++ + mx = max(mx, cnt[s]) return s } dfs(root) - var ans []int - for k, v := range counter { + for k, v := range cnt { if v == mx { ans = append(ans, k) } } - return ans + return } ``` @@ -226,26 +222,22 @@ func findFrequentTreeSum(root *TreeNode) []int { */ function findFrequentTreeSum(root: TreeNode | null): number[] { - const map = new Map(); - let max = 0; - const dfs = (root: TreeNode | null) => { - if (root == null) { + const cnt = new Map(); + let mx = 0; + const dfs = (root: TreeNode | null): number => { + if (!root) { return 0; } const { val, left, right } = root; - const sum = val + dfs(left) + dfs(right); - map.set(sum, (map.get(sum) ?? 0) + 1); - max = Math.max(max, map.get(sum)); - return sum; + const s = val + dfs(left) + dfs(right); + cnt.set(s, (cnt.get(s) ?? 0) + 1); + mx = Math.max(mx, cnt.get(s)!); + return s; }; dfs(root); - const res = []; - for (const [k, v] of map) { - if (v === max) { - res.push(k); - } - } - return res; + return Array.from(cnt.entries()) + .filter(([_, c]) => c === mx) + .map(([s, _]) => s); } ``` @@ -273,33 +265,29 @@ function findFrequentTreeSum(root: TreeNode | null): number[] { use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; -impl Solution { - fn dfs( - root: &Option>>, - map: &mut HashMap, - max: &mut i32, - ) -> i32 { - if root.is_none() { - return 0; - } - let node = root.as_ref().unwrap().borrow(); - let sum = node.val + Self::dfs(&node.left, map, max) + Self::dfs(&node.right, map, max); - map.insert(sum, map.get(&sum).unwrap_or(&0) + 1); - *max = (*max).max(map[&sum]); - sum - } +impl Solution { pub fn find_frequent_tree_sum(root: Option>>) -> Vec { - let mut map = HashMap::new(); - let mut max = 0; - let mut res = Vec::new(); - Self::dfs(&root, &mut map, &mut max); - for (k, v) in map.into_iter() { - if v == max { - res.push(k); + fn dfs(root: Option>>, cnt: &mut HashMap) -> i32 { + if let Some(node) = root { + let l = dfs(node.borrow().left.clone(), cnt); + let r = dfs(node.borrow().right.clone(), cnt); + let s = l + r + node.borrow().val; + *cnt.entry(s).or_insert(0) += 1; + s + } else { + 0 } } - res + + let mut cnt = HashMap::new(); + dfs(root, &mut cnt); + + let mx = cnt.values().cloned().max().unwrap_or(0); + cnt.into_iter() + .filter(|&(_, v)| v == mx) + .map(|(k, _)| k) + .collect() } } ``` diff --git a/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.cpp b/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.cpp index 345a71406d592..edf891649abf1 100644 --- a/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.cpp +++ b/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.cpp @@ -11,24 +11,24 @@ */ class Solution { public: - unordered_map counter; - int mx = 0; - vector findFrequentTreeSum(TreeNode* root) { - mx = INT_MIN; + unordered_map cnt; + int mx = 0; + function dfs = [&](TreeNode* root) -> int { + if (!root) { + return 0; + } + int s = root->val + dfs(root->left) + dfs(root->right); + mx = max(mx, ++cnt[s]); + return s; + }; dfs(root); vector ans; - for (auto& entry : counter) - if (entry.second == mx) - ans.push_back(entry.first); + for (const auto& [k, v] : cnt) { + if (v == mx) { + ans.push_back(k); + } + } return ans; } - - int dfs(TreeNode* root) { - if (!root) return 0; - int s = root->val + dfs(root->left) + dfs(root->right); - ++counter[s]; - mx = max(mx, counter[s]); - return s; - } -}; \ No newline at end of file +}; diff --git a/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.go b/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.go index d0a1658aac153..f81d90a6d5fb6 100644 --- a/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.go +++ b/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.go @@ -6,27 +6,24 @@ * Right *TreeNode * } */ -func findFrequentTreeSum(root *TreeNode) []int { - counter := make(map[int]int) - mx := 0 - var dfs func(root *TreeNode) int +func findFrequentTreeSum(root *TreeNode) (ans []int) { + cnt := map[int]int{} + var mx int + var dfs func(*TreeNode) int dfs = func(root *TreeNode) int { if root == nil { return 0 } s := root.Val + dfs(root.Left) + dfs(root.Right) - counter[s]++ - if mx < counter[s] { - mx = counter[s] - } + cnt[s]++ + mx = max(mx, cnt[s]) return s } dfs(root) - var ans []int - for k, v := range counter { + for k, v := range cnt { if v == mx { ans = append(ans, k) } } - return ans -} \ No newline at end of file + return +} diff --git a/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.java b/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.java index f3a96ea380447..b7c3f1aae1923 100644 --- a/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.java +++ b/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.java @@ -14,24 +14,18 @@ * } */ class Solution { - private Map counter; + private Map cnt = new HashMap<>(); private int mx; public int[] findFrequentTreeSum(TreeNode root) { - counter = new HashMap<>(); - mx = Integer.MIN_VALUE; dfs(root); - List res = new ArrayList<>(); - for (Map.Entry entry : counter.entrySet()) { - if (entry.getValue() == mx) { - res.add(entry.getKey()); + List ans = new ArrayList<>(); + for (var e : cnt.entrySet()) { + if (e.getValue() == mx) { + ans.add(e.getKey()); } } - int[] ans = new int[res.size()]; - for (int i = 0; i < res.size(); ++i) { - ans[i] = res.get(i); - } - return ans; + return ans.stream().mapToInt(i -> i).toArray(); } private int dfs(TreeNode root) { @@ -39,8 +33,7 @@ private int dfs(TreeNode root) { return 0; } int s = root.val + dfs(root.left) + dfs(root.right); - counter.put(s, counter.getOrDefault(s, 0) + 1); - mx = Math.max(mx, counter.get(s)); + mx = Math.max(mx, cnt.merge(s, 1, Integer::sum)); return s; } -} \ No newline at end of file +} diff --git a/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.py b/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.py index fa166a2b2e89f..0a72b00827321 100644 --- a/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.py +++ b/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.py @@ -5,16 +5,16 @@ # self.left = left # self.right = right class Solution: - def findFrequentTreeSum(self, root: TreeNode) -> List[int]: - def dfs(root): + def findFrequentTreeSum(self, root: Optional[TreeNode]) -> List[int]: + def dfs(root: Optional[TreeNode]) -> int: if root is None: return 0 - left, right = dfs(root.left), dfs(root.right) - s = root.val + left + right - counter[s] += 1 + l, r = dfs(root.left), dfs(root.right) + s = l + r + root.val + cnt[s] += 1 return s - counter = Counter() + cnt = Counter() dfs(root) - mx = max(counter.values()) - return [k for k, v in counter.items() if v == mx] + mx = max(cnt.values()) + return [k for k, v in cnt.items() if v == mx] diff --git a/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.rs b/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.rs index 843be9696200d..58973ad05752b 100644 --- a/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.rs +++ b/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.rs @@ -19,32 +19,28 @@ use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; -impl Solution { - fn dfs( - root: &Option>>, - map: &mut HashMap, - max: &mut i32, - ) -> i32 { - if root.is_none() { - return 0; - } - let node = root.as_ref().unwrap().borrow(); - let sum = node.val + Self::dfs(&node.left, map, max) + Self::dfs(&node.right, map, max); - map.insert(sum, map.get(&sum).unwrap_or(&0) + 1); - *max = (*max).max(map[&sum]); - sum - } +impl Solution { pub fn find_frequent_tree_sum(root: Option>>) -> Vec { - let mut map = HashMap::new(); - let mut max = 0; - let mut res = Vec::new(); - Self::dfs(&root, &mut map, &mut max); - for (k, v) in map.into_iter() { - if v == max { - res.push(k); + fn dfs(root: Option>>, cnt: &mut HashMap) -> i32 { + if let Some(node) = root { + let l = dfs(node.borrow().left.clone(), cnt); + let r = dfs(node.borrow().right.clone(), cnt); + let s = l + r + node.borrow().val; + *cnt.entry(s).or_insert(0) += 1; + s + } else { + 0 } } - res + + let mut cnt = HashMap::new(); + dfs(root, &mut cnt); + + let mx = cnt.values().cloned().max().unwrap_or(0); + cnt.into_iter() + .filter(|&(_, v)| v == mx) + .map(|(k, _)| k) + .collect() } } diff --git a/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.ts b/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.ts index a983c32c21ca2..f6031734fd986 100644 --- a/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.ts +++ b/solution/0500-0599/0508.Most Frequent Subtree Sum/Solution.ts @@ -13,24 +13,20 @@ */ function findFrequentTreeSum(root: TreeNode | null): number[] { - const map = new Map(); - let max = 0; - const dfs = (root: TreeNode | null) => { - if (root == null) { + const cnt = new Map(); + let mx = 0; + const dfs = (root: TreeNode | null): number => { + if (!root) { return 0; } const { val, left, right } = root; - const sum = val + dfs(left) + dfs(right); - map.set(sum, (map.get(sum) ?? 0) + 1); - max = Math.max(max, map.get(sum)); - return sum; + const s = val + dfs(left) + dfs(right); + cnt.set(s, (cnt.get(s) ?? 0) + 1); + mx = Math.max(mx, cnt.get(s)!); + return s; }; dfs(root); - const res = []; - for (const [k, v] of map) { - if (v === max) { - res.push(k); - } - } - return res; + return Array.from(cnt.entries()) + .filter(([_, c]) => c === mx) + .map(([s, _]) => s); }