1. 程式人生 > >[LeetCode] Number of Connected Components in an Undirected Graph 無向圖中的連通區域的個數

[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;
    }
};

類似題目:

參考資料: