310. 最小高度树

拓扑排序:

思路:如果要想找最小高度的树,那么只需要找到最里层的所有节点即可(最长的树,是从叶子节点到叶子节点,而最短的树则是从最里层的节点到叶子节点)

拓扑:

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);
    //         }
    //     }
    // }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值