树的直径
难度:
标签:
题目描述
代码结果
运行时间: 43 ms, 内存: 20.2 MB
/*
* Leetcode 1245: Tree Diameter
*
* 思路:
* 1. 将树转换为图,并使用DFS进行两次遍历。
* 2. 第一次DFS找到从任意节点开始的最远节点A。
* 3. 第二次DFS从节点A开始,找到最远的节点B,
* 这样A到B的路径就是树的直径。
*/
import java.util.*;
import java.util.stream.*;
class Solution {
private int maxDiameter = 0;
public int treeDiameter(int[][] edges) {
// 构建图
Map<Integer, List<Integer>> graph = Arrays.stream(edges)
.flatMap(edge -> Stream.of(new int[][]{{edge[0], edge[1]}, {edge[1], edge[0]}}))
.collect(Collectors.groupingBy(
e -> e[0],
Collectors.mapping(e -> e[1], Collectors.toList())
));
// 第一次DFS
int[] firstDFS = dfs(0, -1, graph);
// 第二次DFS
int[] secondDFS = dfs(firstDFS[1], -1, graph);
return secondDFS[0];
}
private int[] dfs(int node, int parent, Map<Integer, List<Integer>> graph) {
return graph.getOrDefault(node, Collections.emptyList()).stream()
.filter(neighbor -> neighbor != parent)
.map(neighbor -> dfs(neighbor, node, graph))
.max(Comparator.comparingInt(result -> result[0]))
.map(result -> new int[]{result[0] + 1, result[1]})
.orElse(new int[]{0, node});
}
}
解释
方法:
该题解利用了广度优先搜索(BFS)算法来计算无向树的直径。解题思路包括:1) 构建无向图的邻接表表示。2) 从任意一个结点(这里选择了结点0)开始进行一次BFS,找到距离这个结点最远的结点,记为farthest_node。3) 从farthest_node再进行一次BFS,找到从这个点出发能到达的最远距离,即为树的直径。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在无向树的直径计算中,选择从任意结点开始进行第一次BFS就能得到最远的结点?是否有可能选择的起始结点会影响到找到的最远结点?
▷🦆
在题解中提到从farthest_node再进行一次BFS可以得到树的直径,这种方法是否在所有类型的树结构中都有效?例如,在非常不平衡的树中也是如此吗?
▷🦆
题解中提到使用邻接表来表示图,为什么选择邻接表而不是邻接矩阵,尤其是在处理树这种特殊形式的图时?
▷🦆
在BFS过程中,题解使用了队列以及已访问节点集合来控制节点访问,这种方法是否最优,还有没有其他方式可以优化BFS的执行效率?
▷