对于一个具有树特征的无向图,我们可选择任何一个节点作为根。图因此可以成为树,在所有可能的树中,具有最小高度的树被称为最小高度树。给出这样的一个图,写出一个函数找到所有的最小高度树并返回他们的根节点。
格式
该图包含 n 个节点,标记为 0 到 n - 1。给定数字 n 和一个无向边 edges 列表(每一个边都是一对标签)。
你可以假设没有重复的边会出现在 edges 中。由于所有的边都是无向边, [0, 1]和 [1, 0] 是相同的,因此不会同时出现在 edges 里。
LeetCode最小高度树.png说明:
- 根据树的定义,树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,一个任何没有简单环路的连通图都是一棵树。
- 树的高度是指根节点和叶子节点之间最长向下路径上边的数量。
思路: 每次删除叶子节点,直到剩下一个或者两个节点就是根节点,为什么剩三个节点不可以呢?
如果剩三个节点的树一定能找到一个节点作为根节点的树高度大于其他两个节点。
因为树就是两个点被一条线链接的无向图,所以先用一个list把树存成无向图的列表。
可以从头边同时进行,查看叶子节点并加入到叶子节点链表(遍历一遍后,叶子节点链表size 为1)。
将叶子节点保存下来。这些叶子节点不用再查,但是剩余的中间节点,要依次查看,把跟第一层叶子节点
有关的图的矩阵里对应的记录全部删除,类似于剥除最外面一圈所有的点。 这个时候就会有第二层叶子节点(那些在列表当中size为1的点),用同样的方法进行剥除。最后留在叶子节点list里面的点即可以为根。
class Solution {
public List<Integer> findMinHeightTrees(int n, int[][] edges) {
List<Integer> leaves = new ArrayList<>();
if (n == 1) {
leaves.add(0);
return leaves;
}
List<Set<Integer>> adj = new ArrayList<>();
for(int i = 0; i < n; i++) adj.add(new HashSet<>());
for(int[] edge : edges){
adj.get(edge[0]).add(edge[1]);
adj.get(edge[1]).add(edge[0]);
}
for(int i = 0; i < n; i++)
if(adj.get(i).size()==1) leaves.add(i);
while(n > 2){
n-=leaves.size();
List<Integer> newLeaves = new ArrayList<>();
for(int i : leaves){
for(int j : adj.get(i)){
adj.get(j).remove(i);
if(adj.get(j).size() ==1) newLeaves.add(j);
}
}
leaves = newLeaves;
}
return leaves;
}
}
网友评论