[LeetCode] 310. Minimum Height Trees

A tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.

Given a tree of n nodes labelled from 0 to n - 1, and an array of n - 1 edges where edges[i] = [ai, bi] indicates that there is an undirected edge between the two nodes ai and bi in the tree, you can choose any node of the tree as the root. When you select a node x as the root, the result tree has height h. Among all possible rooted trees, those with minimum height (i.e. min(h))  are called minimum height trees (MHTs).

Return a list of all MHTs' root labels. You can return the answer in any order.

The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf.

Example 1:

[LeetCode] 310. Minimum Height Trees

Input: n = 4, edges = [[1,0],[1,2],[1,3]]
Output: [1]
Explanation: As shown, the height of the tree is 1 when the root is the node with label 1 which is the only MHT.

Example 2:

[LeetCode] 310. Minimum Height Trees

Input: n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]
Output: [3,4]

Example 3:

Input: n = 1, edges = []
Output: [0]

Example 4:

Input: n = 2, edges = [[0,1]]
Output: [0,1]

Constraints:

  • 1 <= n <= 2 * 104
  • edges.length == n - 1
  • 0 <= ai, bi < n
  • ai != bi
  • All the pairs (ai, bi) are distinct.
  • The given input is guaranteed to be a tree and there will be no repeated edges.

最小高度树。

对于一个具有树特征的无向图,我们可选择任何一个节点作为根。图因此可以成为树,在所有可能的树中,具有最小高度的树被称为最小高度树。给出这样的一个图,写出一个函数找到所有的最小高度树并返回他们的根节点。

格式

该图包含 n 个节点,标记为 0 到 n - 1。给定数字 n 和一个无向边 edges 列表(每一个边都是一对标签)。

你可以假设没有重复的边会出现在 edges 中。由于所有的边都是无向边, [0, 1]和 [1, 0] 是相同的,因此不会同时出现在 edges 里。

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

题目给的input是告诉你有 N 个节点和一些 edges,请你返回最小高度树的根节点。虽然让你返回的是树的根节点,但是其实这是一道图论的题,意思是返回一个节点,他到图中其他节点的距离之和最小。

思路是类似于课程表那样的拓扑排序(参考引用)。根据题意,如果需要知道谁是根节点,那么一定需要计算每两个节点之间的距离。那么对于每个节点,我们可以先统计他们的入度 indegree。这里的入度其实不是非常准确,因为两个节点中间连接的edge是双向的,而不像课程表题那样是单向的。我们这里暂且这样说,其实这里的意思是对于每个节点,统计它有几条边相连。

indegree最小的节点一定不是要找的根节点,因为这些入度为1的节点相当于是在图的最外层,而且 indegree 最小的节点的 indegree 应该是1。既然题目说了是树,就不会有环或者其他corner case。所以还是像课程表题那样,创建一个queue,优先处理入度小的节点。从queue中弹出节点的时候,也需要再次遍历每个弹出节点的邻居节点,并且把每个邻居节点的入度 - 1。此时如果有邻居节点的入度为1的,也加入queue继续循环。while循环退出的时候,queue中剩下的所有节点(有可能有多个),即是题意要求的最小高度树的根节点。

时间O(n)

空间O(n)

Java实现

 1 class Solution {
 2     public List<Integer> findMinHeightTrees(int n, int[][] edges) {
 3         List<Integer> res = new ArrayList<>();
 4         // corner case
 5         if (n == 1) {
 6             res.add(0);
 7             return res;
 8         }
 9 
10         // normal case
11         int[] degree = new int[n];
12         HashMap<Integer, List<Integer>> g = new HashMap<>();
13         for (int i = 0; i < n; i++) {
14             g.put(i, new ArrayList<>());
15         }
16         for (int[] e : edges) {
17             g.get(e[0]).add(e[1]);
18             g.get(e[1]).add(e[0]);
19             degree[e[0]]++;
20             degree[e[1]]++;
21         }
22 
23         Queue<Integer> queue = new LinkedList<>();
24         for (int i = 0; i < n; i++) {
25             if (degree[i] == 1) {
26                 queue.offer(i);
27             }
28         }
29         while (!queue.isEmpty()) {
30             List<Integer> list = new ArrayList<>();
31             int size = queue.size();
32             for (int i = 0; i < size; i++) {
33                 int cur = queue.poll();
34                 list.add(cur);
35                 for (int nei : g.get(cur)) {
36                     degree[nei]--;
37                     if (degree[nei] == 1) {
38                         queue.offer(nei);
39                     }
40                 }
41             }
42             res = list;
43         }
44         return res;
45     }
46 }

 

相关题目

207. Course Schedule

210. Course Schedule II

269. Alien Dictionary

310. Minimum Height Trees

953. Verifying an Alien Dictionary

LeetCode 题目总结

上一篇:昇腾研究之路


下一篇:leetcode 310 最小高度树(拓扑排序变形)