310. Minimum Height Trees
For a undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels.
Format
The graph containsn
nodes which are labeled from0
ton - 1
. You will be given the numbern
and a list of undirectededges
(each edge is a pair of labels).
You can assume that no duplicate edges will appear inedges
. Since all edges are undirected,[0, 1]
is the same as[1, 0]
and thus will not appear together inedges
.
Example 1:
Givenn = 4
,edges = [[1, 0], [1, 2], [1, 3]]
0
|
1
/ \
2 3
return[1]
Example 2:
Givenn = 6
,edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]]
0 1 2
\ | /
3
|
4
|
5
return[3, 4]
Note:
(1) According to thedefinition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected byexactlyone path. In other words, any connected graph without simple cycles is a tree.”
(2) The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf.
S1: bfs, topological sort O(n)
leaf节点只有1个degree(parent), 其他节点至少有两个degree(parent + child)
类似topological sort从后往前,同时从所有leaf节点开始bfs往里找root,每次前进一步:删除所有leaf节点并更新他们的neighbors得到新一组leaf,直到最终剩余1-2个节点即为所求拥有最短路径的root。
vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
if (n == 1) return vector<int>{0}; //没有边的edge case
vector<int> result;
vector<unordered_set<int>> neighbors(n);
vector<int> leafs; //类似queue的作用
for (auto p : edges) {
neighbors[p.first].insert(p.second);
neighbors[p.second].insert(p.first);
}
for (int i = 0; i < n; ++i) {
if (neighbors[i].size() == 1) leafs.push_back(i);
}
while (n > 2) { //最多有两个min root
vector<int> nextLeafs;
for (int i : leafs) {
for (int j : neighbors[i]) {
neighbors[j].erase(i);
if (neighbors[j].size() == 1) nextLeafs.push_back(j);
}
n--;
}
leafs = nextLeafs;
}
return leafs;
}S2: dfs O(n^2)
计算每个节点的height
//超时
class Solution {
public:
vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
vector<int> result;
heights.resize(n);
neighbors.resize(n);
for (auto p : edges) {
neighbors[p.first].push_back(p.second);
neighbors[p.second].push_back(p.first);
}
minHeight = INT_MAX;
for (int i = 0; i < n; ++i) {
heights[i] = dfs(i, -1);
minHeight = min(minHeight, heights[i]);
}
for (int i = 0; i < n; ++i) {
if (heights[i] == minHeight) result.push_back(i);
}
return result;
}
private:
vector<int> heights;
vector<vector<int>> neighbors;
int minHeight;
int dfs(int cur, int pre) {
int h = 1;
for (int i : neighbors[cur]) {
if (i != pre) h = max(h, 1 + dfs(i, cur));
}
return h;
}
};