给定一棵多叉树,求出这棵树的直径,即树上最远两点的距离。
包含n个结点,n-1条边的连通图称为树。
示例1的树如下图所示。其中4到5之间的路径最长,是树的直径,距离为5+2+4=11
数据范围:
,保证最终结果满足
要求:空间复杂度:
,时间复杂度
import java.util.*;
/*
* public class Interval {
* int start;
* int end;
* }
*/
public class Solution {
/**
* 树的直径
* @param n int整型 树的节点个数
* @param Tree_edge Interval类一维数组 树的边
* @param Edge_value int整型一维数组 边的权值
* @return int整型
*/
int max = Integer.MIN_VALUE;
public int solve (int n, Interval[] Tree_edge, int[] Edge_value) {
// write code here
//统计入度为0的节点,为起始节点
boolean[] vis = new boolean[n];
Map<Integer,ArrayList<int[]>> map = new HashMap<>();
for(int i = 0; i < n-1;i++){
ArrayList<int[]> curList = map.getOrDefault(Tree_edge[i].start,new ArrayList<>());
curList.add(new int[]{Tree_edge[i].end,Edge_value[i]});
map.put(Tree_edge[i].start,curList);
vis[Tree_edge[i].end] = true;
}
int start = 0;
for(int i = 0; i < n;i++){
if(!vis[i]){
start = i;
}
}
int cur = process(map,start);
return max;
}
public int process(Map<Integer,ArrayList<int[]>> map,Integer cur){
ArrayList<int[]> curList = map.getOrDefault(cur,new ArrayList<>());
if(curList.size() == 0){
return 0;
}
int[] curArr = new int[curList.size()];
for(int i = 0; i < curList.size();i++){
curArr[i] = process(map,curList.get(i)[0]) + curList.get(i)[1];
}
Arrays.sort(curArr);
int first = curArr[curArr.length-1];
int second = curArr.length - 2 >= 0 ? curArr[curArr.length - 2] : 0;
max = Math.max(max,first+second);
return first;
}
}
import java.util.*;
/*
* public class Interval {
* int start;
* int end;
* }
*/
public class Solution {
/**
* 树的直径
* @param n int整型 树的节点个数
* @param Tree_edge Interval类一维数组 树的边
* @param Edge_value int整型一维数组 边的权值
* @return int整型
*/
static int[] h;
static int[] e;
static int[] w;
static int[] ne;
static int idx = 0;
static int[] d;//以N为根节点的子树的深度;
static int ans = 0;
static boolean[] st; //无向图防止子节点回到父节点
static int cao;
static void add(int a, int b, int c){
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
public int solve (int n, Interval[] Tree_edge, int[] Edge_value) {
// write code here
int N = n;
int M = N*3;
e = new int[M];
h = new int[N];
w = new int[M];
ne = new int[M];
d = new int[N];
st = new boolean[N];
Arrays.fill(h, -1);
for (int i = 0; i < n-1; i++){
add(Tree_edge[i].start, Tree_edge[i].end, Edge_value[i]);
add(Tree_edge[i].end, Tree_edge[i].start, Edge_value[i]);
}
dfs(1);
Arrays.fill(d, 0);
Arrays.fill(st, false);
dfs(ans);
return d[ans];
}
void dfs(int u) {
if (st[u]) return;
st[u] = true; // 标记一下,记录为已经被搜索过了,下面进行搜索过程
for (int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if (!st[j]) { // 是否被遍历过
d[j]=d[u]+w[i];
if(d[j]>d[ans])ans=j;
dfs(j);
}
}
}
} //可参考https://www.bilibili.com/video/BV1qA411t7LR?from=search&seid=13550771883067952709,比较类似
import java.util.*;
public class Solution {
ArrayList<ArrayList<Integer>> nei = new ArrayList<>();//邻接列表——>存储无向图的关系
HashMap<ArrayList<Integer>, Integer> edge = new HashMap<>();//哈希表:存储边的权重
int ans=Integer.MIN_VALUE;//最终结果
public int solve (int n, Interval[] Tree_edge, int[] Edge_value) {
//初始化邻接表
for(int i=0;i<n;i++){
nei.add(new ArrayList<>());
}
//邻接表和哈希表的写入
for(int i=0;i<Tree_edge.length;i++){
//无向表,所以两次写入
int a=Tree_edge[i].start;
int b=Tree_edge[i].end;
//邻接列表
nei.get(a).add(b);
nei.get(b).add(a);
//哈希表
ArrayList<Integer> tmp=new ArrayList<>();
tmp.add(a);
tmp.add(b);
edge.put(tmp,Edge_value[i]);
tmp=new ArrayList<>();
tmp.add(b);
tmp.add(a);
edge.put(tmp,Edge_value[i]);
}
boolean[] v=new boolean[n];
dfs(0,v);
return ans;
}
private int dfs(int root,boolean[] v){
//初始化及出口条件
v[root]=true;
ArrayList<Integer> ls=new ArrayList<>();
ls=nei.get(root);
int m1=Integer.MIN_VALUE,m2=Integer.MIN_VALUE;//m1距离该节点最长的值,m2代表第2长的值
//int m1=0,m2=0;
//出口条件
for(int k:ls){
if(!v[k]){//标记为已经访问过的,则不访问
ArrayList<Integer> e=new ArrayList<>();
e.add(root);
e.add(k);
int res=Integer.MIN_VALUE;
//递归,res代表该节点到本次的探索的长度
res=dfs(k,v)+edge.get(e);
//保证m1最长,m2第2长
if(res>m1){
m2=m1;
m1=res;
}
else if(res>m2)
m2=res;
}
}
//判断条件
if(m1==Integer.MIN_VALUE){
ans = Math.max(ans, 0);
}
else{
if(m2==Integer.MIN_VALUE)
ans = Math.max(ans, m1);
else
ans=Math.max(ans,m1+m2);
}
//从本节点出发,一直搜索到最后。将该节点设为未访问,便于从其它节点访问本节点
v[root]=false;
return Math.max(m1,0);//如果m1为末端或者为负,就要舍弃掉从root出发的所有路径,返回0
} public class Solution {
/**
* 树的直径
* @param n int整型 树的节点个数
* @param Tree_edge Interval类一维数组 树的边
* @param Edge_value int整型一维数组 边的权值
* @return int整型
*/
public int solve (int n, Interval[] Tree_edge, int[] Edge_value) {
// write code here
if(Tree_edge == null || Edge_value == null || Tree_edge.length != Edge_value.length){return 0;}
Map<Integer, List<Edge>> graph = new HashMap<>();
int len = Tree_edge.length;
for(int i = 0; i < len; ++i){
Interval inter = Tree_edge[i];
int start = inter.start;
int end = inter.end;
int w = Edge_value[i];
Edge e1 = new Edge(end, w);
if(!graph.containsKey(start)){
List<Edge> temp = new ArrayList<>();
graph.put(start, temp);
}
graph.get(start).add(e1);
Edge e2 = new Edge(start, w);
if(!graph.containsKey(end)){
List<Edge> temp = new ArrayList<>();
graph.put(end, temp);
}
graph.get(end).add(e2);
}
int[] remote = {0, 0}; // remote[0] 代表以0为起点的最长路径长度, remote[1]代表最长路径的终点
dfs(graph, 0, -1, 0, remote);
int[] res = {0, 0};
dfs(graph, remote[1], -1, 0, res);
return res[0];
}
private class Edge{
int end;
int w;
Edge(int end, int w){
this.end = end;
this.w = w;
}
}
private void dfs(Map<Integer, List<Edge>> graph, int from, int prev, int path, int[] res){
List<Edge> edges = graph.get(from);
for(Edge edge: edges){
if(edge.end != prev){
path += edge.w;
if(path > res[0]){
res[0] = path;
res[1] = edge.end;
}
dfs(graph, edge.end, from, path, res);
path -= edge.w; // 回溯
}
}
}
}