【算法】树的直径

文章目录

  • 1245. 树的直径
  • Tag

1245. 树的直径

如果不懂DFS,BFS,和递归方面的内容,下面就可以不用看了。

树上任意两节点之间最长的简单路径即为树的「直径」

方法很简单,找一个节点A,从A出发到距离A最远的节点B,然后从节点B出发,找到距离节点B最远的节点C。然后B~C就是这个树中最远的距离,也称为树的直径,即这个路径上边的数量。

这个结论是 对 M叉树。

证明方法 略,去百度。

简单来说,分为2步,每一步都是找距离当前节点最远的一个节点。这个可以使用BFS,也可以使用DFS处理。

当然也可以使用树形DP来处理。

当节点 v 的处于最长的路径上,这个最长的路径L 可能的组成就有几个情况。

1 以 V为 root向下 的最长的2个路径【这2个路径不能有公共边】 组成。

2 V 在路径上,并且 从V向下的最长路径,一定是这个L的组成部分。

定义节点的编号0~n-1,一共n个节点。

定义一个dfs(int u,int fa) u 表示当前的节点, fa 表示其 父节点【也可以认为是从fa节点遍历过来到达u】。

同时为了记录u的最长的2个路径,定义d1[n],d2[n] 分别表示从 u出发的最长路径d1[u],和 次长路径d2[u].

时间复杂度是O(N),空间复杂度是O(N)

int res = 0;
    public List<Integer>[] map;
    public int[] d1,d2;
    public int treeDiameter(int[][] edges) {
        map = new ArrayList[edges.length+1];
        for(int i=0 ; i<map.length ; i++){
            map[i] = new ArrayList<>();
        }
        int n = map.length;
        d1 = new int[n];
        d2 = new int[n];

        for(int[] edge : edges){
            map[edge[0]].add(edge[1]);
            map[edge[1]].add(edge[0]);
        } 
        dfs(0,-1); 
        return res;
    } 
    
    public void dfs(int u,int fa){ 
        List<Integer> list = map[u];
        d1[u]= d2[u] =0; 
        for(int next : list){
            if(next== fa) continue;
            dfs(next,u);
            int t = d1[next]+1;
            if(t>d1[u]){
                d2[u] = d1[u];
                d1[u] = t; 
            } else if(t>d2[u]){
                d2[u] =t;
            }
        }
        res = Math.max(res,d2[u]+d1[u]); 
        return  ; 
    }

Tag

DP,树形DP

你可能感兴趣的:(数据结构与算法,算法,动态规划)