给定一棵多叉树,求出这棵树的直径,即树上最远两点的距离。
包含n个结点,n-1条边的连通图称为树。
示例1的树如下图所示。其中4到5之间的路径最长,是树的直径,距离为5+2+4=11
数据范围:,保证最终结果满足
要求:空间复杂度:,时间复杂度
6,[[0,1],[1,5],[1,2],[2,3],[2,4]],[3,4,2,1,5]
11
2,[[0,1],[1,2]],[1]
1
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; // 回溯 } } } }