圖:310.最小高度數, 題解

axuu發表於2024-09-16

310. 最小高度樹 - 力扣(LeetCode)

參考題解:

演算法邏輯:演算法的核心思路是逐層剪去葉子節點,直到剩下的節點是最小高度樹的根

示例:

假設有如下的樹結構:

    0
   / \
  1   2
     / \
    3   4

初始時,葉子節點是134,剪掉這些葉子節點後,樹變成:

    0
     \
      2

再次剪掉葉子節點2,最終剩下的節點是0,0就是最小高度樹的根節點。

相同的邊,還有一種最小高度數的情況是:

      2
   / \  \
  3   4 0
           \
            1

初始時剪掉葉子節點3,4,1;再次剪掉葉子節點0,最終剩下的節點是2,2就是最小高度數的根節點。

具體程式碼如下:

class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
        vector<int> res;
        // 如果只有一個節點,那麼它就是最小高度樹
        if (n == 1) {
            res.push_back(0);
            return res;
        }

        // 建立各個節點的出度表
        vector<int> degree(n, 0);
        // 建立圖關係,在每個節點的列表中儲存相連節點
        vector<vector<int>> map(n);
        for (const auto& edge : edges) {
            degree[edge[0]]++;
            degree[edge[1]]++; // 出度++
            map[edge[0]].push_back(edge[1]); // 新增相鄰節點
            map[edge[1]].push_back(edge[0]);
        }

        // 建立佇列
        queue<int> q;
        // 把所有出度為1的節點,也就是葉子節點入隊
        for (int i = 0; i < n; ++i) {
            if (degree[i] == 1) {
                q.push(i);
            }
        }

        // 迴圈條件是佇列不空
        while (!q.empty()) {
            res.clear(); // 每層迴圈都要new一個新的結果集合
            int size = q.size(); // 每一層的節點的數量
            for (int i = 0; i < size; ++i) {
                int cur = q.front();
                q.pop();
                res.push_back(cur); // 將當前節點加入結果集

                for (int neighbor : map[cur]) {
                    degree[neighbor]--;
                    if (degree[neighbor] == 1) {
                        q.push(neighbor); // 如果是葉子節點,入隊
                    }
                }
            }
        }

        return res; // 返回最後一次儲存的列表
    }
};

相關文章