310. Minimum Height Trees(BFS)

1. 题目描述

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 contains n nodes which are labeled from 0 to n - 1. You will be given the number n and a list of undirected edges (each edge is a pair of labels).

You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges.

Example 1:

Given n = 4, edges = [[1, 0], [1, 2], [1, 3]]

    0
    |
    1
   / \
  2   3

return [1]

2. 代码

2.1 特别版

根据题意,给定的图是一个具有“树”特征的图,因此该图是无环的(树是无环的),因此在讨论算法的时候,不需要考虑有环的情况(实际上以下算法对有环的情况是不成立的)。
a. 一种解题思路是:最小高度是最长路径的“一半”!
b. 另一种思路是,不断删除叶子结点,最终会达到根结点,如果具有最小高度树的根结点是唯一的,那么最后只会剩下一个结点,否则剩下两个结点(不会有其他情况,思考为什么?)

class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {

     //邻接表
        vector<unordered_set<int>> adj(n);
        for(pair<int, int> e : edges) {
            adj[e.first].insert(e.second);
            adj[e.second].insert(e.first);
        }
        //只有一个结点
        vector<int> current;
        if(n == 1) {
            current.push_back(0);
            return current;
        }
        //最底层叶结点
        for(int i = 0; i < adj.size(); ++i) {
            if(adj[i].size() == 1) {
                current.push_back(i);
            }
        }
        //不断删除叶结点,直到根结点
        while(true) {
            vector<int> next;
            for(int u : current) {
                for(int v : adj[u]) {
                    adj[v].erase(u);
                    if(adj[v].size() == 1) next.push_back(v);
                }
            }
            //如果next为空,那么必定是剩下两个结点或一个结点
            //思考为什么?
            if(next.size() == 0)
                return current;
            current = next;
        }

    }

};

注:如果current最后只剩下一个结点的话,那么下一个next不加增加,第二层for循环不再进入,next为空。
如果current最后一趟剩下两个结点的话,那么从第二层for循环出来后,adj[v]的size为0,next为空。

2.2 小白版

用常规的BFS,会超时,以下是Time Exceeding代码。注意还有内存空间上也有较大开销。

class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {

        vector<vector<int>> vE(n,vector<int>(n,-1));

        for(int i = 0; i < edges.size(); i++) {
            vE[edges[i].first].push_back(edges[i].second);
            vE[edges[i].second].push_back(edges[i].first);
        }

        int vector<int> res;
        vector<int> height(n,0);
        for(int u = 0; u < n; u++){
            height[u] = bfs(u, vE);
        }
        sort(height.begin(), height.end());
        int min = height[0];
        res.push_back(min);
        for(int h = 1; h < height.size(); h++) {
            if(h == min) {
                res.push_back(h);
            }
        }
        return res;

    }
    int bfs(int u, vector<vector<int>>& vE) {
        queue<int> q;
        q.push(u);
        int level = 0;
        while(!q.empty()) {
            level++;
            for(int s = q.size(); s > 0; s--) {
                int v = q.front();
                q.pop();
                for(int i = 0; i < vE[v].size(); i++) {
                    q.push(vE[v][i]);
                }
            }
        }
        return level;
    }
};

邮箱联系:sysuygm@163.com
欢迎赐教!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值