Skip to content

Commit ddd0b82

Browse files
committed
minimum height trees
1 parent e55ac6a commit ddd0b82

File tree

2 files changed

+93
-3
lines changed

2 files changed

+93
-3
lines changed

src/main/java/joshua/leetcode/bfs/MinimumHeightTrees.java

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package joshua.leetcode.bfs;
22

3+
import java.util.HashSet;
4+
import java.util.LinkedList;
35
import java.util.List;
6+
import java.util.Set;
47

58
/**
69
* 310. Minimum Height Trees<br/>
@@ -57,9 +60,10 @@ public abstract class MinimumHeightTrees {
5760

5861
/**
5962
* 思路来自拓扑排序。
60-
* 这个问题先简化为假如能找到图的最长路径,那么minimum height tree的顶点就是这条路径的中间节点,如果路径长度为奇数就是1个,
63+
* 这个问题先简化为,假如能找到图的最长路径,那么minimum height tree的顶点就是这条路径的中间节点,如果路径长度为奇数就是1个,
6164
* 路径长度为偶数就是2个。
62-
* 如何找到这个中间节点可以用两端出发,步长为1同时移动,相遇时的节点就是中间节点。
65+
* 如何找到这个中间节点可以从路径两端出发,以步长为1同时移动,相遇时的节点就是中间节点。
66+
*
6367
* 这个方法借鉴到这个问题上,从所有的叶子节点出发,每次剪去所有的叶子节点,然后更新所有其他节点的degree,直到只剩下不多于两个节点
6468
* 迭代终止。
6569
* <p/>
@@ -70,7 +74,46 @@ public static class Solution1 extends MinimumHeightTrees {
7074

7175
@Override
7276
public List<Integer> findMinHeightTrees(int n, int[][] edges) {
73-
return null;
77+
LinkedList<Integer> leaves = new LinkedList<Integer>();
78+
if (n == 1) {
79+
leaves.add(0);
80+
return leaves;
81+
}
82+
// 初始化一个类似邻接矩阵(Adjacency Matrix)标识的结构从来存储每个顶点上的边信息,set的大小就是外层list对应下标的度,
83+
// 这个信息用来判断叶子节点
84+
Set[] adjMatrix = new Set[n];
85+
for (int[] edge : edges) {
86+
if (adjMatrix[edge[0]] == null) {
87+
Set<Integer> adjs = new HashSet<Integer>();
88+
adjMatrix[edge[0]] = adjs;
89+
}
90+
adjMatrix[edge[0]].add(edge[1]);
91+
if (adjMatrix[edge[1]] == null) {
92+
Set<Integer> adjs = new HashSet<Integer>();
93+
adjMatrix[edge[1]] = adjs;
94+
}
95+
adjMatrix[edge[1]].add(edge[0]);
96+
}
97+
// 初始化叶子节点
98+
for(int i = 0; i < adjMatrix.length; i ++) {
99+
if (adjMatrix[i].size() == 1) {
100+
leaves.add(i);
101+
}
102+
}
103+
// 裁剪叶子节点
104+
while(n > 2) {
105+
n -= leaves.size();
106+
int size = leaves.size();
107+
for(int i = 0; i< size; i++) {
108+
int leave = leaves.removeFirst();
109+
int adj = (Integer)adjMatrix[leave].iterator().next();
110+
adjMatrix[adj].remove(leave);
111+
if (adjMatrix[adj].size() == 1) {
112+
leaves.add(adj);
113+
}
114+
}
115+
}
116+
return leaves;
74117
}
75118
}
76119
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package joshua.leetcode.bfs;
2+
3+
import static org.junit.Assert.assertEquals;
4+
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
import org.junit.Before;
9+
import org.junit.Test;
10+
11+
import com.google.common.collect.Lists;
12+
import com.google.common.collect.Maps;
13+
14+
public class MinimumHeightTreesTest {
15+
16+
private Map<Param, List<Integer>> cases = Maps.newHashMap();
17+
18+
@Before
19+
public void setUp() {
20+
// int[][] edges = new int[][]{{0, 3}, {1, 3}, {2, 3}, {4, 3}, {5, 4}};
21+
// List<Integer> result = Lists.newArrayList(3, 4);
22+
// cases.put(new Param(6, edges), result);
23+
// case 2
24+
int[][] edges2 = new int[][]{{0, 1}, {0, 2}};
25+
cases.put(new Param(3, edges2), Lists.newArrayList(0));
26+
}
27+
28+
@Test
29+
public void testSolution1() {
30+
MinimumHeightTrees solution = new MinimumHeightTrees.Solution1();
31+
for(Param param : cases.keySet()) {
32+
List<Integer> roots = solution.findMinHeightTrees(param.numOfVertex, param.edges);
33+
assertEquals(cases.get(param), roots);
34+
}
35+
}
36+
37+
class Param {
38+
int numOfVertex;
39+
40+
int[][] edges;
41+
42+
public Param(int numOfVertex, int[][] edges) {
43+
this.numOfVertex = numOfVertex;
44+
this.edges = edges;
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)