310. 最小高度树 【我爱 拓扑】

35 阅读1分钟

310. 最小高度树

image.png

方法:拓扑排序

class Solution:
    def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
        # 拓扑排序  
        # 假设  树中 距离最长的 两个节点为 (x, y) 
        # 最小树 的根节点  为 中间结点

        # 操作 
        # 度 为 1  的节点  不断入栈
        # 直到 剩余节点数 <= 2
        if n == 1:
            return [0]

        g = [[] for _ in range(n)]
        deg = [0] * n 
        for u, v in edges:
            g[u].append(v)
            g[v].append(u)
            deg[u] += 1
            deg[v] += 1
        
        q = [i for i, d in enumerate(deg) if d == 1] # 度 为 1 的 结点 入栈
        remainModes = n 
        while remainModes > 2:
            remainModes -= len(q)
            nxt = []  # 下一批 度为 1 的结点
            for u in q:
                for v in g[u]:
                    deg[v] -= 1
                    if deg[v] == 1:
                        nxt.append(v)
            q = nxt                     

        return q

image.png

class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
        if (n == 1) return {0};

        vector<int> deg(n);
        vector<vector<int>> adj(n);
        for (auto & edge : edges){
            adj[edge[0]].emplace_back(edge[1]);
            adj[edge[1]].emplace_back(edge[0]);
            ++deg[edge[0]];
            ++deg[edge[1]];
        }

        vector<int> q; // 要 返回 vector<int> 直接用这个
        for (int i = 0; i < n; ++i){// 让 度为 0 的结点 入队
            if (deg[i] == 1){
                q.emplace_back(i);
            }
        }

        // BFS 依次 去掉 度为 0 的结点
        int remainNodes = n;
        while (remainNodes  > 2){
            remainNodes -= q.size();
            vector<int> nxt; // 记录 下一层 入度为 0 的结点
            for (auto & u : q){
                for (auto & v : adj[u]){
                    if (--deg[v] == 1){// 先进行 自减, 再进行判断
                        nxt.emplace_back(v);
                    }
                }
            }
            q = move(nxt);
        }
        return q;
    }
};