目录

0310:最小高度树(★)

力扣第 310 题

题目

树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,任何一个没有简单环路的连通图都是一棵树。

给你一棵包含 n 个节点的树,标记为 0n - 1 。给定数字 n 和一个有 n - 1 条无向边的 edges 列表(每一个边都是一对标签),其中 edges[i] = [ai, bi] 表示树中节点 aibi 之间存在一条无向边。

可选择树中任何一个节点作为根。当选择节点 x 作为根节点时,设结果树的高度为 h 。在所有可能的树中,具有最小高度的树(即,min(h))被称为 最小高度树

请你找到所有的 最小高度树 并按 任意顺序 返回它们的根节点标签列表。

树的 高度 是指根节点和叶子节点之间最长向下路径上边的数量。

示例 1:

输入:n = 4, edges = [[1,0],[1,2],[1,3]]
输出:[1]
解释:如图所示,当根是标签为 1 的节点时,树的高度是 1 ,这是唯一的最小高度树。

示例 2:

输入:n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]
输出:[3,4]

提示:

  • 1 <= n <= 2 * 104
  • edges.length == n - 1
  • 0 <= ai, bi < n
  • ai != bi
  • 所有 (ai, bi) 互不相同
  • 给定的输入 保证 是一棵树,并且 不会有重复的边

相似问题:

分析

可以用拓扑排序,一层层去掉叶子,最里面的一层即是所求。证明见 力扣

解答

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Solution:
    def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
        g = [[] for _ in range(n)]
        for a,b in edges:
            g[a].append(b)
            g[b].append(a)
        deg = [len(row) for row in g]
        Q = [u for u in range(n) if deg[u]<=1]
        res = []
        while Q:
            res,Q = Q,[]
            for u in res:
                for v in g[u]:
                    deg[v]-=1
                    if deg[v]==1:
                        Q.append(v)
        return res 

73 ms

*附加

也可以用换根dp的方法

  • 初始节点 0 作为根
  • 第一遍 dfs 得到每个节点的高 H
  • 第二遍 dfs 得到每个节点向上能走的最大距离 up
  • max(H,up) 即是该节点作为根的高度
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution:
    def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
        g = [[] for _ in range(n)]
        for a,b in edges:
            g[a].append(b)
            g[b].append(a)
        H = [0]*n
        def dfs(u,f):
            for v in g[u]:
                if v!=f:
                    dfs(v,u)
                    H[u] = max(H[u],H[v]+1)
        dfs(0,-1)
        up = [0]*n
        def dfs(u,f):
            A = [1+H[v] for v in g[u] if v!=f]+[up[u],0]
            a,b = nlargest(2,A)
            for v in g[u]:
                if v!=f:
                    up[v]=1+b if 1+H[v]==a else 1+a
                    dfs(v,u)
        dfs(0,-1)
        res = [max(a,b) for a,b in zip(H,up)]
        mi = min(res)
        return [u for u in range(n) if res[u]==mi]

187 ms