拓扑排序:
思路:如果要想找最小高度的树,那么只需要找到最里层的所有节点即可(最长的树,是从叶子节点到叶子节点,而最短的树则是从最里层的节点到叶子节点)
拓扑:
1. 寻找度为1的所有节点加入队列(无向图只考虑度即可)
2, 循环遍历队列,直至队列为空时,即认为遍历结束
(1)从队列中取出一个节点,将与该节点相连的边(度)都去掉
(2)检查取出当前边后,与该节点相连的边的度是否为1,如果为1加入队列
(3) 将从队列中取出的节点放入结果集
3. 返回当前结果集
class Solution {
public:
/* 拓扑排序 */
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
vector<int> res; // 记录结果节点
if(n==1||edges.empty()){
return vector<int>{0};
}
queue<int> q; // 记录所有度为1的节点
vector<int> degree(n,0); // 记录所有节点的度
vector<vector<int>> g(n);
// 记录所有的节点的度
for(auto e:edges){
g[e[0]].emplace_back(e[1]);
g[e[1]].emplace_back(e[0]);
degree[e[0]]++;
degree[e[1]]++;
}
// 将所有度为1的节点加入到队列
for(int i=0;i<n;i++){
if(degree[i] == 1){
q.push(i);
}
}
// 循环遍历,去除所有的叶子节点
while(!q.empty()){
res.clear();
int len = q.size();
while(len--){
int top = q.front();
q.pop();
res.push_back(top);
for(auto c:g[top]){
degree[c]--;
if(degree[c]==1){
q.push(c);
}
}
}
}
return res;
}
/*深度优先遍历: 暴力搜索,时间复杂度o(n^2),超时*/
// vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
// int h = 1; // 当前高度
// // 遍历每个节点
// map<int,int> mp; // 记录以每个顶点为根节点的高度
// for(int i=0;i<n;i++){
// vector<int> path(n,0); // 记录该顶点是否已经遍历过
// path[i] = 1;
// deep(n,edges,i,i,path,mp,h);
// }
// int min_h = INT_MAX;
// // 取出树的最小高度
// for(auto m:mp){
// if(m.second<min_h){
// min_h = m.second;
// }
// }
// // 将所有高度为最小高度的树的根节点取出,
// vector<int> result;
// for(auto m:mp){
// if(m.second == min_h){
// result.emplace_back(m.first);
// }
// }
// return result;
// }
// void deep(int &n,vector<vector<int>>& edges,int point,int &root,vector<int> &path,map<int,int>& mp,int h){
// // 更新以点point为根的高度
// if(h>mp[root]){
// mp[root] = h;
// }
// for(auto e:edges){
// // 寻找未遍历过的节点
// if(e[0] == point&&path[e[1]] == 0){
// path[e[1]] = 1;
// deep(n,edges,e[1],root,path,mp,h+1);
// }
// if(e[1] == point&&path[e[0]] == 0){
// path[e[0]] = 1;
// deep(n,edges,e[0],root,path,mp,h+1);
// }
// }
// }
};