Skip to content

Commit b279ba8

Browse files
[LEET-508] add 508
1 parent b6b6f70 commit b279ba8

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

leetcode-algorithms/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
|-----|----------------|---------------|---------------|---------------|-------------|--------------|-----
66
|515|[Find Largest Value in Each Tree Row](https://leetcode.com/problems/find-largest-value-in-each-tree-row/)|[Solution](../../master/leetcode-algorithms/src/main/java/com/stevesun/solutions/FindLargestValueinEachTreeRow.java) | O(n) |O(k) | Medium| BFS
77
|513|[Find Bottom Left Tree Value](https://leetcode.com/problems/find-bottom-left-tree-value/)|[Solution](../../master/leetcode-algorithms/src/main/java/com/stevesun/solutions/FindBottomLeftValue.java) | O(n) |O(k) | Medium| BFS
8+
|508|[Most Frequent Subtree Sum](https://leetcode.com/problems/most-frequent-subtree-sum/)|[Solution](../../master/leetcode-algorithms/src/main/java/com/stevesun/solutions/MostFrequentSubtreeSum.java) | O(n) |O(n) | Medium| DFS, Tree
89
|506|[Relative Ranks](https://leetcode.com/problems/relative-ranks/)|[Solution](../../master/leetcode-algorithms/src/main/java/com/stevesun/solutions/RelativeRanks.java) | O(nlogn) |O(n) | Easy|
910
|505|[The Maze II](https://leetcode.com/problems/the-maze-ii/)|[Solution](../../master/leetcode-algorithms/src/main/java/com/stevesun/solutions/TheMazeII.java) | O(m*n) |O(m*n) | Medium| BFS
1011
|504|[Base 7](https://leetcode.com/problems/base-7/)|[Solution](../../master/leetcode-algorithms/src/main/java/com/stevesun/solutions/Base7.java) | O(1) |O(1) | Easy|
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.stevesun.solutions;
2+
3+
import com.stevesun.common.classes.TreeNode;
4+
5+
import java.util.*;
6+
7+
/**
8+
* 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.
9+
10+
Examples 1
11+
Input:
12+
5
13+
/ \
14+
2 -3
15+
return [2, -3, 4], since all the values happen only once, return all of them in any order.
16+
17+
Examples 2
18+
Input:
19+
20+
5
21+
/ \
22+
2 -5
23+
return [2], since 2 happens twice, however -5 only occur once.
24+
25+
Note: You may assume the sum of values in any subtree is in the range of 32-bit signed integer.
26+
*/
27+
public class MostFrequentSubtreeSum {
28+
29+
//my purely original but verbose solution
30+
public int[] findFrequentTreeSum(TreeNode root) {
31+
if (root == null) return new int[]{};
32+
33+
Map<TreeNode, Integer> map = new HashMap();
34+
postOrder(root, map);
35+
36+
Map<Integer, Integer> frequencyMap = new HashMap<>();
37+
for (Map.Entry entry : map.entrySet()) {
38+
frequencyMap.put((Integer) entry.getValue(), frequencyMap.getOrDefault(entry.getValue(), 0)+1);
39+
}
40+
41+
List<Map.Entry<Integer, Integer>> list = new LinkedList<>(frequencyMap.entrySet());
42+
Collections.sort(list, (o1, o2) -> (o2.getValue()).compareTo(o1.getValue()));
43+
44+
int mostFrequency = list.get(0).getValue();
45+
List<Integer> topFrequencyList = new ArrayList<>();
46+
topFrequencyList.add(list.get(0).getKey());
47+
int i = 1;
48+
while (i < list.size() && list.get(i).getValue() == mostFrequency) {
49+
topFrequencyList.add(list.get(i).getKey());
50+
i++;
51+
}
52+
53+
int[] result = new int[topFrequencyList.size()];
54+
for (int j = 0; j < topFrequencyList.size(); j++) {
55+
result[j] = topFrequencyList.get(j);
56+
}
57+
58+
return result;
59+
}
60+
61+
private int postOrder(TreeNode root, Map<TreeNode, Integer> map) {
62+
int left = 0;
63+
int right = 0;
64+
if (root.left != null) {
65+
left = postOrder(root.left, map);
66+
}
67+
if (root.right != null) {
68+
right = postOrder(root.right, map);
69+
}
70+
if (root.left == null && root.right == null) {
71+
map.put(root, root.val);
72+
return root.val;
73+
}
74+
int sum = left + right + root.val;
75+
map.put(root, sum);
76+
return sum;
77+
}
78+
79+
//a more concise and space-efficient solution: https://discuss.leetcode.com/topic/77775/verbose-java-solution-postorder-traverse-hashmap-18ms
80+
//the key difference between the above post and my original solution is that it's using Frequency as the key of the HashMap
81+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.stevesun;
2+
3+
import com.stevesun.common.classes.TreeNode;
4+
import com.stevesun.solutions.MostFrequentSubtreeSum;
5+
import org.junit.Before;
6+
import org.junit.BeforeClass;
7+
import org.junit.Test;
8+
9+
import static org.junit.Assert.assertArrayEquals;
10+
11+
public class MostFrequentSubtreeSumTest {
12+
private static MostFrequentSubtreeSum test;
13+
private static int[] expected;
14+
private static int[] actual;
15+
private static TreeNode root;
16+
17+
@BeforeClass
18+
public static void setup(){
19+
test = new MostFrequentSubtreeSum();
20+
}
21+
22+
@Before
23+
public void setupForEachTest(){
24+
expected = new int[]{};
25+
actual = new int[]{};
26+
}
27+
28+
@Test
29+
public void test1(){
30+
root = new TreeNode(5);
31+
root.left = new TreeNode(2);
32+
root.right = new TreeNode(-3);
33+
expected = new int[]{2,-3,4};
34+
actual = test.findFrequentTreeSum(root);
35+
assertArrayEquals(expected, actual);
36+
}
37+
38+
@Test
39+
public void test2(){
40+
root = new TreeNode(5);
41+
root.left = new TreeNode(2);
42+
root.right = new TreeNode(-5);
43+
expected = new int[]{2};
44+
actual = test.findFrequentTreeSum(root);
45+
assertArrayEquals(expected, actual);
46+
}
47+
}

0 commit comments

Comments
 (0)