[LeetCode] Number of Connected Components in an Undirected Graph 無向圖中的連通區域的個數


 

Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), write a function to find the number of connected components in an undirected graph.

Example 1:

     0          3

     |          |

     1 --- 2    4

Given n = 5 and edges = [[0, 1], [1, 2], [3, 4]], return 2.

Example 2:

     0           4

     |           |

     1 --- 2 --- 3

Given n = 5 and edges = [[0, 1], [1, 2], [2, 3], [3, 4]], return 1.

 Note:

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.

 

這道題讓我們求無向圖中連通區域的個數,LeetCode中關於圖Graph的題屈指可數,解法都有類似的特點,都是要先構建鄰接鏈表Adjacency List來做。這道題的一種解法是利用DFS來做,思路是給每個節點都有個flag標記其是否被訪問過,對於一個未訪問過的節點,我們將結果自增1,因為這肯定是一個新的連通區域,然后我們通過鄰接鏈表來遍歷與其相鄰的節點,並將他們都標記成已訪問過,遍歷完所有的連通節點后我們繼續尋找下一個未訪問過的節點,以此類推直至所有的節點都被訪問過了,那么此時我們也就求出來了連通區域的個數。

 

解法一:

class Solution {
public:
    int countComponents(int n, vector<pair<int, int> >& edges) {
        int res = 0;
        vector<vector<int> > g(n);
        vector<bool> v(n, false);
        for (auto a : edges) {
            g[a.first].push_back(a.second);
            g[a.second].push_back(a.first);
        }
        for (int i = 0; i < n; ++i) {
            if (!v[i]) {
                ++res;
                dfs(g, v, i);
            }
        }
        return res;
    }
    void dfs(vector<vector<int> > &g, vector<bool> &v, int i) {
        if (v[i]) return;
        v[i] = true;
        for (int j = 0; j < g[i].size(); ++j) {
            dfs(g, v, g[i][j]);
        }
    }
};

 

這道題還有一種比較巧妙的方法,不用建立鄰接鏈表,也不用DFS,思路是建立一個root數組,下標和節點值相同,此時root[i]表示節點i屬於group i,我們初始化了n個部分 (res = n),假設開始的時候每個節點都屬於一個單獨的區間,然后我們開始遍歷所有的edge,對於一條邊的兩個點,他們起始時在root中的值不相同,這時候我們我們將結果減1,表示少了一個區間,然后更新其中一個節點的root值,使兩個節點的root值相同,那么這樣我們就能把連通區間的所有節點的root值都標記成相同的值,不同連通區間的root值不相同,這樣也能找出連通區間的個數。

 

解法二:

class Solution {
public:
    int countComponents(int n, vector<pair<int, int> >& edges) {
        int res = n;
        vector<int> root(n);
        for (int i = 0; i < n; ++i) root[i] = i;
        for (auto a : edges) {
            int x = find(root, a.first), y = find(root, a.second);
            if (x != y) {
                --res;
                root[y] = x;
            }
        }
        return res;
    }
    int find(vector<int> &root, int i) {
        while (root[i] != i) i = root[i];
        return i;
    }
};

 

類似題目:

Clone Graph

Minimum Height Trees 

Course Schedule

Course Schedule II

 

參考資料:

https://leetcode.com/discuss/77308/accepted-dfs-in-c

https://leetcode.com/discuss/77027/c-solution-using-union-find

https://leetcode.com/discuss/76519/similar-to-number-of-islands-ii-with-a-findroot-function

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM