题目链接、描述
https://www.lintcode.com/problem/1298
对于一个树状的无向图,选择任何一个节点作为根。这个图就变成了一个有根树。在所有可能的有根树中,有最小高度的树叫做最小高度树(minimum height trees, MHTs)。给定这样的图,找出所有的MHTs,返回根标记的数组。
格式
图包含了n个节点,标记从0到n-1。给定n和一个无向边列表edges。每一个边是一组节点标记。
假定没有重复的遍。由于所有的边是无向边,所以[0, 1]和[1, 0]是等价的,所以也不会同时出现在edges当中。
(1)根据树的定义:一个树是一个无向图,且任意两个顶点都有唯一一条路径连通。也即,树中没有环。
(2)树的高度是树根和叶子之间的最长边数。
样例
样例1
输入: n = 4, edges = [[1, 0], [1, 2], [1, 3]]
输出: [1]
解释:
0
|
1
/ \
2 3
样例2
输入: n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]]
输出: [3, 4]
解释:
0 1 2
\ | /
3
|
4
|
5
思路
前置知识:图、拓扑排序
这道题可以用拓扑排序的思想来做,虽然不是有序图,但是当节点入度为1时,必然为叶子节点。
由此可见当我们用BFS从叶子节点一层一层搜索下去时,最后一组的节点就是最短高度根节点。
我们的目标是找到那个根节点。
创建图
统计每个节点的入度
把所有入度为1的节点放入queue (叶子节点)
从每个叶子节点找到他们各自的根节点,把他们的入度减一
当根节点入度为1时, 放入queue
最后的一组queue就是最后的根节点, 也就是答案。
代码
public class Solution {
/**
* @param n: n nodes labeled from 0 to n - 1
* @param edges: a undirected graph
* @return: a list of all the MHTs root labels
* we will sort your return value in output
*/
public List<Integer> findMinHeightTrees(int n, int[][] edges) {
/*
这道题可以用拓扑排序的思想来做,虽然不是有序图,但是当节点入度为1时,必然为叶子节点。
由此可见当我们用BFS从叶子节点一层一层搜索下去时,最后一组的节点就是最短高度根节点。
我们的目标是找到那个根节点。
创建图
统计每个节点的入度
把所有入度为1的节点放入queue (叶子节点)
从每个叶子节点找到他们各自的根节点,把他们的入度减一
当根节点入度为1时, 放入queue
最后的一组queue就是最后的根节点, 也就是答案。
*/
if(edges==null|| edges.length ==0 || edges[0].length ==0 || n ==1)
return Arrays.asList(0);
Map<Integer,Node> graph = new HashMap<>(); //图
for (int i = 0; i <n ; i++) {
graph.put(i,new Node(i));
}
for (int[] edge : edges) {
int v1 = edge[0],v2 = edge[1];
Node from = graph.get(v1);
Node to = graph.get(v2);
from.nexts.add(to);
to.nexts.add(from);
to.in++;
from.in++;
}
Queue<Node> queue = new LinkedList<>(); //宽度优先遍历的核心
for(int k: graph.keySet()){
if(graph.get(k).in ==1){
queue.add(graph.get(k));
}
}
// System.out.println(queue.size());
List<Integer> ans = new ArrayList<>();//记录最后一组queue的节点值,就是答案
while (!queue.isEmpty()){
int size = queue.size();
ans.clear();
for (int i = 0; i <size ; i++) {
Node poll = queue.poll();
ans.add(poll.data);
for (Node next : poll.nexts) {
if(--next.in ==1){
queue.add(next);
}
}
}
//System.out.println(ans);
}
return ans;
}
static class Node{ //图的节点的定义
int data;
int in;
List<Node> nexts;
public Node(int d){
data =d;
in =0;
nexts = new ArrayList<>();
}
}
}