链接:https://leetcode-cn.com/problems/minimum-height-trees/
BFS 超级简单 注释超级详细
简单分析过程:
首先,我们看了样例,发现这个树并不是二叉树,是多叉树。
然后,我们可能想到的解法是:根据题目的意思,就挨个节点遍历bfs,统计下每个节点的高度,然后用map存储起来,后面查询这个高度的集合里最小的就可以了。
但是这样会超时的。
于是我们看图(题目介绍里面的图)分析一下,发现,越是靠里面的节点越有可能是最小高度树。
所以,我们可以这样想,我们可以倒着来。
我们从边缘开始,先找到所有出度为1的节点,然后把所有出度为1的节点进队列,然后不断地bfs,最后找到的就是两边同时向中间靠近的节点,那么这个中间节点就相当于把整个距离二分了,那么它当然就是到两边距离最小的点啦,也就是到其他叶子节点最近的节点了。
然后,就可以写代码了。
class Solution {
public:
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
if(n == 1) {
return vector<int>{0};
}
// 度,n为节点的个数
vector<int> degree(n, 0);
std::unordered_map<int, set<int>> adj;
for(int i = 0; i < edges.size(); ++i) {
const std::vector<int>& temp = edges[i];
// 存储邻接矩阵
adj[temp[0]].insert(temp[1]);
adj[temp[1]].insert(temp[0]);
// 记录节点度
++degree[temp[0]];
++degree[temp[1]];
}
queue<int> que;
for(int i = 0; i < n; ++i) {
// 将边数量为1的节点加入
if(degree[i] == 1) {
que.push(i);
}
}
vector<int> result;
while(!que.empty()) {
int size = que.size();
result.clear();
// 遍历所有度为1的节点,
for(int i = 0; i < size; ++i) {
int front = que.front();
degree[front] = 0;
que.pop();
// 将度为1的相邻的节点的度减1
result.push_back(front);
for(auto ite : adj[front]) {
--degree[ite];
if(degree[ite] == 1) {
que.push(ite);
}
}
}
}
return result;
}
};