对于一个具有树特征的无向图,我们可选择任何一个节点作为根。图因此可以成为树,在所有可能的树中,具有最小高度的树被称为最小高度树。给出这样的一个图,写出一个函数找到所有的最小高度树并返回他们的根节点。
格式
该图包含 n 个节点,标记为 0 到 n - 1。给定数字 n 和一个无向边 edges 列表(每一个边都是一对标签)。
你可以假设没有重复的边会出现在 edges 中。由于所有的边都是无向边, [0, 1]和 [1, 0] 是相同的,因此不会同时出现在 edges 里。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-height-trees
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
学习的别人思路代码
原文链接:https://leetcode-cn.com/problems/minimum-height-trees/solution/javati-jie-bfssi-lu-hen-qing-xi-by-lemon-lc/
class Solution {
/*
* 解题思路:既然要求最小高度,那么从我们直觉来看,结点肯定是在最内部的,因为题目说了是无向图,所以越靠近边缘,高度肯定就会越大,
* 最终的结点就是位于最中间的1个或2个结点。
*
* 1、首先对于数据进行初始化,这里使用degree数组来描述当前结点的度(因为我们每次都是要从边缘进行逐层的删除,而边缘就是度为1的结点)
* 并且使用邻接表来存储和当前结点相邻的结点。
* 2、将度为1的结点(边缘结点)插入到队列中,我们这里使用一个List<Integer> res来存每一层的结点,最后一次插入的所有结点就一定是最后一层的结点
* (也就是我们需要的最内部层的结点)。
* 3、返回res数组即可。
*/
public List<Integer> findMinHeightTrees(int n, int[][] edges) {
List<Integer> res = new ArrayList<Integer>();
if (n==1) {
res.add(0);
return res;
}
//构造邻接表
List<Set<Integer>> matrixList = new ArrayList<Set<Integer>>();
//节点的度
int[] degree = new int[n];
for(int i=0;i<n;i++){
matrixList.add(new HashSet<Integer>());
}
for(int i=0;i<edges.length;i++){
int row = edges[i][0];
int col = edges[i][1];
matrixList.get(row).add(col);
matrixList.get(col).add(row);
degree[row] = degree[row]+1;
degree[col] = degree[col]+1;
}
Queue<Integer> queue = new LinkedList<Integer>();
for(int i=0;i<n;i++){
if(degree[i]==1){
queue.offer(i);
degree[i] = -1;//相当于删除
}
}
//进行bfs遍历,不断删除度为0的节点
while(!queue.isEmpty()){
res.clear();
int size = queue.size();
for (int j = 0; j < size; j++) {
int curNode = queue.poll();
res.add(curNode);
for (int node : matrixList.get(curNode)) {
degree[node]--;
if (degree[node] == 1) {
queue.add(node);
}
}
}
}
return res;
}
}
暴力法,会超时
class Solution {
class Helper{
int root;//根节点的值
int deep;//根节点对应的树的深度值
Helper(){}
Helper(int root,int deep){
this.root = root;
this.deep = deep;
}
}
public int min_value = Integer.MAX_VALUE;
/*
* 基本思路:(超时)
* 1、根据输入的边的信息构造无向图矩阵(超时50/66),构造邻接表(63/66)
* 2、采用回溯法,进行bfs遍历,同时记录下遍历的深度,存入list中.
* 在遍历过程中维护一个全局最小深度值,一旦超过深度,直接返回.加快速度
* 3、对list中的值进行判断,将合法的值返回
*/
public List<Integer> findMinHeightTrees2(int n, int[][] edges) {
List<Helper> list = new ArrayList<Helper>();
//构造邻接表
List<Set<Integer>> matrixList = new ArrayList<Set<Integer>>();
for(int i=0;i<n;i++){
matrixList.add(new HashSet<Integer>());
}
for(int i=0;i<edges.length;i++){
int row = edges[i][0];
int col = edges[i][1];
matrixList.get(row).add(col);
matrixList.get(col).add(row);
}
//进行bfs遍历
for(int i=0;i<n;i++){
boolean[] visit = new boolean[n];//判断该节点是否访问过
Queue<Integer> queue = new LinkedList<Integer>();
queue.offer(i);
visit[i] = true;
bfs(queue,1,1,i,matrixList,visit,list);
}
//对list中的值进行合法性判断
List<Integer> res = new ArrayList<Integer>();
for(Helper hp : list){
if(hp.deep==min_value){
res.add(hp.root);
}
}
return res;
}
/*
* queue代表同一层的所有节点值队列
* deep以root为根节点的当前树的深度
* num遍历的节点个数
* root根节点(一但确定就不改变)
*/
public void bfs(Queue<Integer> queue, int deep, int num, int root, List<Set<Integer>> matrixList, boolean[] visit, List<Helper> list){
if(deep>min_value) return;
if(num==visit.length){//所有节点遍历完
min_value = Math.min(min_value,deep);
Helper helper = new Helper(root,deep);
list.add(helper);
return;
}
//进行bfs
int size = queue.size();
int n = 0;
while(n<size){
int v = queue.poll();
for(Integer value : matrixList.get(v)){
if(!visit[value]){
queue.offer(value);
visit[value] = true;
num++;
}
}
n++;
}
bfs(queue,deep+1,num,root,matrixList,visit,list);
}
}