leetcode [310] 最小高度树
Contact me:
Blog -> https://cugtyt.github.io/blog/index
Email -> cugtyt@qq.com
GitHub -> Cugtyt@GitHub
对于一个具有树特征的无向图,我们可选择任何一个节点作为根。图因此可以成为树,在所有可能的树中,具有最小高度的树被称为最小高度树。给出这样的一个图,写出一个函数找到所有的最小高度树并返回他们的根节点。
格式
该图包含 n 个节点,标记为 0 到 n - 1。给定数字 n 和一个无向边 edges 列表(每一个边都是一对标签)。
你可以假设没有重复的边会出现在 edges 中。由于所有的边都是无向边, [0, 1]和 [1, 0] 是相同的,因此不会同时出现在 edges 里。
示例 1:
输入: n = 4, edges = [[1, 0], [1, 2], [1, 3]]
0
|
1
/ \
2 3
输出: [1]
示例 2:
输入: n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]]
0 1 2
\ | /
3
|
4
|
5
输出: [3, 4]
说明:
根据树的定义,树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,一个任何没有简单环路的连通图都是一棵树。
树的高度是指根节点和叶子节点之间最长向下路径上边的数量。
来自题解:
把所有只连接一个点加入外层洋葱队列(集合),然后一层一层往内剥,直到剩余1或2个点时停止,这两个点都可以作为树的根节点。
时间复杂度,边哈希O(E),队列初始化O(N),剥洋葱过程O(N)。
class Solution:
def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
if n == 1:
return [0]
adj = defaultdict(set) #字典初始化为集合
for i, j in edges:
adj[i] |= {j} #把边哈希化,方便调用
adj[j] |= {i}
degree1 = {i for i in adj if len(adj[i]) == 1} #建立初始宽搜队列,长度为1时代表只连接一个点
while n > 2:
newdegree1 = set() #临时队列
for i in degree1:
j = adj[i].pop() #把连接点取出
adj[j] -= {i} #连接是双向的,所以要删除关系
if len(adj[j]) == 1: #更新后,如果长度为1时则加入下一个轮队列
newdegree1 |= {j}
n -= 1 #删除计数
degree1 = newdegree1
return list(degree1)