-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathMinimumHeightTrees.java
106 lines (89 loc) · 3.09 KB
/
MinimumHeightTrees.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package binarytree.problems;
import graph.Graph;
import utils.Reader;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.io.IOException;
// Leetcode Problem: https://leetcode.com/problems/minimum-height-trees/description/
public class MinimumHeightTrees {
public static void main (String[] args) throws IOException {
Reader reader = new Reader();
int n = reader.nextInt();
int m = reader.nextInt();
int[][] edges = new int[m][2];
for (int i=0; i<m; i++) {
edges[i][0] = reader.nextInt();
edges[i][1] = reader.nextInt();
}
MinimumHeightTrees obj = new MinimumHeightTrees();
System.out.println(Arrays.toString(obj.findMinHeightTrees(n, edges).toArray()));
}
public List<Integer> findMinHeightTrees(int n, int[][] edges) {
Graph graph = new Graph(n);
for (int i=0; i<edges.length; i++) {
graph.addDirectedEdge(edges[i][0], edges[i][1]);
graph.addDirectedEdge(edges[i][1], edges[i][0]);
}
int[] vis = new int[n];
int[] depth = new int[n];
dfs(0, graph, vis, depth);
int endPoint1 = findMaxDepthNode(depth);
initialiseDepth(depth);
initialiseDepth(vis);
dfs(endPoint1, graph, vis, depth);
int endPoint2 = findMaxDepthNode(depth);
initialiseDepth(vis);
int[] parent = new int[n];
parent[endPoint2] = -1;
computeParent(endPoint2, graph, vis, parent);
ArrayList<Integer> longestPath = new ArrayList<>();
int cnode = endPoint1;
while (cnode != -1) {
longestPath.add(cnode);
cnode = parent[cnode];
}
List<Integer> roots = new ArrayList<>();
if (longestPath.size()%2 == 0) {
roots.add(longestPath.get(longestPath.size()/2));
roots.add(longestPath.get(longestPath.size()/2 - 1));
} else {
roots.add(longestPath.get(longestPath.size()/2));
}
return roots;
}
public void computeParent(int node, Graph graph, int[] vis, int[] parent) {
vis[node] = 1;
for (int adjNode : graph.getAdjacentNodes(node)) {
if (vis[adjNode] == 0) {
parent[adjNode] = node;
computeParent(adjNode, graph, vis, parent);
}
}
}
public void dfs(int node, Graph graph, int[] vis, int[] depth) {
vis[node] = 1;
for (int adjNode : graph.getAdjacentNodes(node)) {
if (vis[adjNode] == 0) {
depth[adjNode] = depth[node] + 1;
dfs(adjNode, graph, vis, depth);
}
}
}
public int findMaxDepthNode (int[] depth) {
int endPoint = -1;
int maxDepth = -1;
for (int i=0; i<depth.length; i++) {
if (maxDepth < depth[i]) {
maxDepth = depth[i];
endPoint = i;
}
}
return endPoint;
}
public void initialiseDepth(int[] depth) {
for (int i=0; i<depth.length; i++) {
depth[i] = 0;
}
}
}