zoukankan      html  css  js  c++  java
  • [LeetCode] 1245. Tree Diameter

    Given an undirected tree, return its diameter: the number of edges in a longest path in that tree.

    The tree is given as an array of edges where edges[i] = [u, v] is a bidirectional edge between nodes u and v.  Each node has labels in the set {0, 1, ..., edges.length}.

    Example 1:

    Input: edges = [[0,1],[0,2]]
    Output: 2
    Explanation: 
    A longest path of the tree is the path 1 - 0 - 2.
    

    Example 2:

    Input: edges = [[0,1],[1,2],[2,3],[1,4],[4,5]]
    Output: 4
    Explanation: 
    A longest path of the tree is the path 3 - 2 - 1 - 4 - 5.

    Constraints:

    • 0 <= edges.length < 10^4
    • edges[i][0] != edges[i][1]
    • 0 <= edges[i][j] <= edges.length
    • The given edges form an undirected tree.

    树的直径。

    给你这棵「无向树」,请你测算并返回它的「直径」:这棵树上最长简单路径的 边数。

    我们用一个由所有「边」组成的数组 edges 来表示一棵无向树,其中 edges[i] = [u, v] 表示节点 u 和 v 之间的双向边。

    树上的节点都已经用 {0, 1, ..., edges.length} 中的数做了标记,每个节点上的标记都是独一无二的。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/tree-diameter
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    虽然题目描述是一棵树,其实这是一道图论的题目,我给出一个DFS的思路。首先我们还是建图,图建立好之后,我们用一个helper函数进行DFS遍历。对于当前某个节点的所有邻居,我们对邻居再做DFS遍历并对长度 + 1。这里我们需要利用到类似543题的思路,对于同一个node延伸出去的长度,由于我们不知道遍历的方向,所以我们记录 max1 和 max2,表示经过某个节点能组成的最大的长度和次大的长度。DFS函数在返回的时候,依然返回最长的长度max1但是对于全局变量res的更新,是res = Math.max(res, max1 + max2)。因为res本质上记录的是经过当前节点的diameter,而DFS往上一层返回的值相当于是父节点要知道到底哪个孩子返回的路径是最长的。

    时间O(n)

    空间O(n)

    Java实现

     1 class Solution {
     2     int res = 0;
     3 
     4     public int treeDiameter(int[][] edges) {
     5         List<Integer>[] graph = new List[edges.length + 1];
     6         for (int i = 0; i < graph.length; i++) {
     7             graph[i] = new ArrayList<>();
     8         }
     9         for (int[] e : edges) {
    10             graph[e[0]].add(e[1]);
    11             graph[e[1]].add(e[0]);
    12         }
    13         dfs(graph, 0, -1);
    14         return res;
    15     }
    16 
    17     private int dfs(List<Integer>[] graph, int cur, int prev) {
    18         List<Integer> list = graph[cur];
    19         int max1 = 0;
    20         int max2 = 0;
    21         // 遍历每个邻居节点
    22         for (int nei : list) {
    23             // 防止走回头路
    24             if (nei != prev) {
    25                 int max = dfs(graph, nei, cur) + 1;
    26                 if (max >= max1) {
    27                     max2 = max1;
    28                     max1 = max;
    29                 } else if (max >= max2) {
    30                     max2 = max;
    31                 }
    32                 // res记录的是经过当前节点最长的diameter是多少
    33                 // 但是DFS函数返回的是当前节点能找到的最长的长度,把这个信息返回给父节点
    34                 res = Math.max(res, max1 + max2);
    35             }
    36         }
    37         return max1;
    38     }
    39 }

    相关题目

    543. Diameter of Binary Tree

    1245. Tree Diameter

    LeetCode 题目总结

  • 相关阅读:
    面试题25二叉树中和为某一值得路径+递归函数详细解析
    [Codeforces 1199D]Welfare State(线段树)
    [Codeforces 1199C]MP3(离散化+二分答案)
    [Codeforces 1191D] Tokitsukaze, CSL and Stone Game(博弈论)
    [Codeforces 639F] Bear and Chemistry (Tarjan+虚树)(有详细注释)
    [HDU5807] [BestCoder Round #86 1004] Keep In Touch (DP)
    [Codeforces712D] Memory and Scores(DP+前缀和优化)(不用单调队列)
    [Codeforces722E] Research Rover (dp+组合数学)
    [POJ3612] Telephone Wire(暴力dp+剪枝)
    [Codeforces600E] Lomsat gelral(树上启发式合并)
  • 原文地址:https://www.cnblogs.com/cnoodle/p/14418906.html
Copyright © 2011-2022 走看看