Skip to content

Commit 60a076d

Browse files
solves #310: Minimum Height Trees in java
1 parent a4a68b5 commit 60a076d

5 files changed

+239
-44
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@
261261
| 306 | [Additive Number](https://leetcode.com/problems/additive-number) | | |
262262
| 307 | [Range Sum Query - Mutable](https://leetcode.com/problems/range-sum-query-mutable) | | |
263263
| 309 | [Best Time to Buy and Sell Stock with Cooldown](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown) | | |
264-
| 310 | [Minimum Height Trees](https://leetcode.com/problems/minimum-height-trees) | | |
264+
| 310 | [Minimum Height Trees](https://leetcode.com/problems/minimum-height-trees) | [![Java](assets/java.png)](src/MinimumHeightTrees.java) | |
265265
| 311 | 🔒 [Sparse Matrix Multiplication](https://leetcode.com/problems/sparse-matrix-multiplication) | | |
266266
| 313 | [Super Ugly Number](https://leetcode.com/problems/super-ugly-number) | | |
267267
| 314 | 🔒 [Binary Tree Vertical Order Traversal](https://leetcode.com/problems/binary-tree-vertical-order-traversal) | | |

src/AlienDictionary.java

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// https://leetcode.com/problems/alien-dictionary
2+
// T: O()
3+
// S: O()
4+
5+
import java.util.*;
6+
7+
public class AlienDictionary {
8+
public String alienOrder(String[] words) {
9+
final Map<Character, Set<Character>> graph = createGraphFrom(words);
10+
return lexicographicallySmallest(graph);
11+
}
12+
13+
private static String lexicographicallySmallest(Map<Character, Set<Character>> graph) {
14+
final Map<Character, Integer> inDegree = computeInDegree(graph);
15+
final Queue<Character> queue = new LinkedList<>();
16+
final StringBuilder builder = new StringBuilder();
17+
add0InDegreeInQueue(queue, inDegree);
18+
19+
while (!queue.isEmpty()) {
20+
final char c = queue.poll();
21+
builder.append(c);
22+
for (char neighbour : graph.getOrDefault(c, new HashSet<>())) {
23+
inDegree.put(neighbour, inDegree.get(neighbour) - 1);
24+
if (inDegree.get(neighbour) == 0) {
25+
queue.add(neighbour);
26+
}
27+
}
28+
graph.remove(c);
29+
}
30+
31+
if (graph.isEmpty()) {
32+
return builder.toString();
33+
}
34+
return "";
35+
}
36+
37+
private static Map<Character, Set<Character>> createGraphFrom(String[] words) {
38+
final Map<Character, Set<Character>> graph = new HashMap<>();
39+
addAllLettersInGraph(graph, words);
40+
for (int i = 0 ; i < words.length ; i++) {
41+
for (int j = i + 1 ; j < words.length ; j++) {
42+
if (words[i].equals(words[j])) {
43+
continue;
44+
}
45+
final char[] charDiff = firstDifferentCharacter(words[i], words[j]);
46+
if (charDiff.length == 0) {
47+
continue;
48+
}
49+
final Set<Character> set = graph.getOrDefault(charDiff[0], new HashSet<>());
50+
set.add(charDiff[1]);
51+
graph.putIfAbsent(charDiff[0], set);
52+
}
53+
}
54+
return graph;
55+
}
56+
57+
private static void addAllLettersInGraph(Map<Character, Set<Character>> graph, String[] words) {
58+
for (String word : words) {
59+
for (int i = 0 ; i < word.length() ; i++) {
60+
graph.putIfAbsent(word.charAt(i), new HashSet<>());
61+
}
62+
}
63+
}
64+
65+
private static char[] firstDifferentCharacter(String s1, String s2) {
66+
for (int i = 0 ; i < s1.length() && i < s2.length() ; i++) {
67+
if (s1.charAt(i) != s2.charAt(i)) {
68+
return new char[] { s1.charAt(i), s2.charAt(i) };
69+
}
70+
}
71+
return new char[] {};
72+
}
73+
74+
private static Map<Character, Integer> computeInDegree(Map<Character, Set<Character>> graph) {
75+
final Map<Character, Integer> inDegree = new HashMap<>();
76+
for (Set<Character> set : graph.values()) {
77+
for (char c : set) {
78+
inDegree.put(c, inDegree.getOrDefault(c, 0) + 1);
79+
}
80+
}
81+
return inDegree;
82+
}
83+
84+
private static void add0InDegreeInQueue(Queue<Character> queue, Map<Character, Integer> inDegree) {
85+
for (Map.Entry<Character, Integer> entry : inDegree.entrySet()) {
86+
if (entry.getValue() == 0) {
87+
queue.add(entry.getKey());
88+
}
89+
}
90+
}
91+
}

src/HelloWorld.java

+64-42
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,80 @@
1-
import java.util.*;
1+
import java.util.ArrayList;
2+
import java.util.HashMap;
3+
import java.util.HashSet;
4+
import java.util.List;
5+
import java.util.Map;
6+
import java.util.PriorityQueue;
7+
import java.util.Queue;
8+
import java.util.Set;
29

310
public class HelloWorld {
4-
private record Edge(int vertex, int time) {}
5-
6-
public int networkDelayTime(int[][] times, int n, int k) {
7-
final Map<Integer, Map<Integer, Integer>> graph = createGraph(times);
8-
final Map<Integer, Integer> delayTimes = dijkstra(graph, k);
9-
if (delayTimes.size() != n) {
10-
return -1;
11-
}
12-
return delayTimes.values().stream().max(Integer::compare).get();
13-
}
14-
15-
// T: O(E), S: O(E)
16-
private static Map<Integer, Map<Integer, Integer>> createGraph(int[][] edges) {
17-
final Map<Integer, Map<Integer, Integer>> graph = new HashMap<>();
18-
for (int[] edge : edges) {
19-
final int from = edge[0], to = edge[1], weight = edge[2];
20-
final Map<Integer, Integer> neighbours = graph.getOrDefault(from, new HashMap<>());
21-
neighbours.put(to, weight);
22-
graph.putIfAbsent(from, neighbours);
23-
}
24-
return graph;
11+
// T: O(V + E) S: O(V + E)
12+
public int[] findOrder(int numCourses, int[][] prerequisites) {
13+
final Map<Integer, Set<Integer>> graph = createGraph(prerequisites);
14+
final int[] inDegree = computeInDegree(numCourses, prerequisites);
15+
return orderOfCourses(graph, inDegree);
2516
}
2617

27-
// T: O(V + E logV)
28-
private static Map<Integer, Integer> dijkstra(Map<Integer, Map<Integer, Integer>> graph, int start) {
29-
final Map<Integer, Integer> distances = new HashMap<>();
30-
final Queue<Edge> queue = new PriorityQueue<>(Comparator.comparingInt(a -> a.time));
31-
queue.add(new Edge(start, 0));
18+
// T: O(V + E) S: O(V)
19+
private static int[] orderOfCourses(Map<Integer, Set<Integer>> graph, int[] inDegree) {
20+
final Queue<Integer> queue = new PriorityQueue<>();
21+
final List<Integer> order = new ArrayList<>();
22+
addAll0InDegreeToQueue(queue, inDegree);
3223

3324
while (!queue.isEmpty()) {
34-
final Edge edge = queue.poll();
35-
if (edge.time >= distances.getOrDefault(edge.vertex, Integer.MAX_VALUE)) {
36-
continue;
25+
final int vertex = queue.poll();
26+
order.add(vertex);
27+
for (int neighbour : graph.getOrDefault(vertex, new HashSet<>())) {
28+
inDegree[neighbour]--;
29+
if (inDegree[neighbour] == 0) {
30+
queue.add(neighbour);
31+
}
3732
}
33+
graph.remove(vertex);
34+
}
35+
36+
if (order.size() != inDegree.length) {
37+
return new int[] {};
38+
}
39+
return toArray(order);
40+
}
3841

39-
distances.put(edge.vertex, edge.time);
42+
private static int[] toArray(List<Integer> list) {
43+
final int[] array = new int[list.size()];
44+
for (int i = 0 ; i < array.length ; i++) {
45+
array[i] = list.get(i);
46+
}
47+
return array;
48+
}
4049

41-
for (Map.Entry<Integer, Integer> entry : graph.getOrDefault(edge.vertex, new HashMap<>()).entrySet()) {
42-
final int neighbour = entry.getKey(), time = entry.getValue();
43-
queue.add(new Edge(neighbour, edge.time + time));
50+
// T: O(E) S: O(1)
51+
private static void addAll0InDegreeToQueue(Queue<Integer> queue, int[] inDegree) {
52+
for (int i = 0 ; i < inDegree.length ; i++) {
53+
if (inDegree[i] == 0) {
54+
queue.add(i);
4455
}
4556
}
46-
47-
return distances;
4857
}
4958

50-
public static void main(String[] args) {
51-
int[] b = new int[] {1, 2, 3};
52-
int[] a = b;
53-
System.out.println(Arrays.toString(a));
54-
b = new int[] {5, 6, 7};
55-
System.out.println(Arrays.toString(a));
59+
// T: O(E) S: O(E)
60+
private static int[] computeInDegree(int n, int[][] edges) {
61+
final int[] inDegree = new int[n];
62+
for (int[] edge : edges) {
63+
final int to = edge[0];
64+
inDegree[to]++;
65+
}
66+
return inDegree;
67+
}
5668

69+
// T: O(|E|), S: O(E)
70+
private static Map<Integer, Set<Integer>> createGraph(int[][] edges) {
71+
final Map<Integer, Set<Integer>> graph = new HashMap<>();
72+
for (int[] edge : edges) {
73+
final int to = edge[0], from = edge[1];
74+
final Set<Integer> set = graph.getOrDefault(from, new HashSet<>());
75+
set.add(to);
76+
graph.putIfAbsent(from, set);
77+
}
78+
return graph;
5779
}
5880
}

src/MaximumDepthOfNAryTree.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
// https://leetcode.com/problems/maximum-depth-of-n-ary-tree
2+
// T: O(N)
3+
// S: O(logN)
4+
15
import java.util.List;
26

37
public class MaximumDepthOfNAryTree {
4-
private static class Node {
8+
public static class Node {
59
public int val;
610
public List<Node> children;
711

src/MinimumHeightTrees.java

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// https://leetcode.com/problems/minimum-height-trees
2+
// T: O(N)
3+
// S: O(N)
4+
5+
import java.util.ArrayList;
6+
import java.util.HashMap;
7+
import java.util.HashSet;
8+
import java.util.List;
9+
import java.util.Map;
10+
import java.util.Set;
11+
12+
public class MinimumHeightTrees {
13+
public List<Integer> findMinHeightTrees(int n, int[][] edges) {
14+
if (n == 0) return new ArrayList<>();
15+
if (n == 1) return new ArrayList<>() {{ add(0); }};
16+
17+
final Map<Integer, Set<Integer>> graph = createGraph(edges);
18+
return minHeightTreeRoots(graph);
19+
}
20+
21+
// T: O(N), S: O(N)
22+
private static List<Integer> minHeightTreeRoots(Map<Integer, Set<Integer>> graph) {
23+
final int[] degree = computeDegree(graph);
24+
Set<Integer> leafNodes = addLeafNodes(degree);
25+
26+
while (graph.size() > 2) {
27+
final Set<Integer> newLeafNodes = new HashSet<>();
28+
for (int leafNode : leafNodes) {
29+
degree[leafNode]--;
30+
for (int neighbour : graph.get(leafNode)) {
31+
degree[neighbour]--;
32+
if (degree[neighbour] == 1) {
33+
newLeafNodes.add(neighbour);
34+
}
35+
}
36+
graph.remove(leafNode);
37+
}
38+
leafNodes = newLeafNodes;
39+
}
40+
41+
return new ArrayList<>(graph.keySet());
42+
}
43+
44+
// T: O(N), S: O(N)
45+
private static Set<Integer> addLeafNodes(int[] degree) {
46+
final Set<Integer> leafNodes = new HashSet<>();
47+
for (int i = 0 ; i < degree.length ; i++) {
48+
if (degree[i] == 1) {
49+
leafNodes.add(i);
50+
}
51+
}
52+
return leafNodes;
53+
}
54+
55+
// T: O(N), S: O(N)
56+
private static int[] computeDegree(Map<Integer, Set<Integer>> graph) {
57+
final int[] degree = new int[graph.size()];
58+
for (Map.Entry<Integer, Set<Integer>> entry : graph.entrySet()) {
59+
degree[entry.getKey()] = entry.getValue().size();
60+
}
61+
return degree;
62+
}
63+
64+
// T: O(N), S: O(N)
65+
private static Map<Integer, Set<Integer>> createGraph(int[][] edges) {
66+
final Map<Integer, Set<Integer>> graph = new HashMap<>();
67+
for (int[] edge : edges) {
68+
final int from = edge[0], to = edge[1];
69+
final Set<Integer> fromSet = graph.getOrDefault(from, new HashSet<>());
70+
final Set<Integer> toSet = graph.getOrDefault(to, new HashSet<>());
71+
fromSet.add(to);
72+
toSet.add(from);
73+
graph.putIfAbsent(from, fromSet);
74+
graph.putIfAbsent(to, toSet);
75+
}
76+
return graph;
77+
}
78+
}

0 commit comments

Comments
 (0)