Description
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:
Given n = 5
and edges = [[0, 1], [1, 2], [3, 4]]
, return 2
.
Example 2:
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
.
Solution
DFS
用Map来保存节点连接的关系。注意set.add返回的boolean表示是否成功加入到set中,可以用来精简代码。
class Solution {
public int countComponents(int n, int[][] edges) {
if (n < 2 || edges.length < 1) {
return n;
}
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < n; ++i) {
map.put(i, new LinkedList<>());
}
for (int[] edge : edges) {
map.get(edge[0]).add(edge[1]);
map.get(edge[1]).add(edge[0]);
}
Set<Integer> visited = new HashSet<>();
int count = 0;
for (int i = 0; i < n; ++i) {
if (visited.add(i)) { // i has not been handled
dfsCountComponents(i, map, visited);
++count;
}
}
return count;
}
public void dfsCountComponents(
int i, Map<Integer, List<Integer>> map, Set<Integer> visited) {
for (Integer neighbor : map.get(i)) {
if (visited.add(neighbor)) {
dfsCountComponents(neighbor, map, visited);
}
}
}
}
BFS
class Solution {
public int countComponents(int n, int[][] edges) {
if (n < 2 || edges.length < 1) {
return n;
}
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < n; ++i) {
map.put(i, new LinkedList<>());
}
for (int[] edge : edges) {
map.get(edge[0]).add(edge[1]);
map.get(edge[1]).add(edge[0]);
}
Set<Integer> visited = new HashSet<>();
Queue<Integer> queue = new LinkedList<>();
int count = 0;
for (int i = 0; i < n; ++i) {
if (visited.add(i)) { // visited first then add to queue
queue.add(i);
while (!queue.isEmpty()) {
Integer curr = queue.poll();
for (Integer neighbor : map.get(curr)) {
if (visited.add(neighbor)) {
queue.add(neighbor);
}
}
}
++count;
}
}
return count;
}
}
Union-Find, time O(n), space O(n)
class Solution {
public int countComponents(int n, int[][] edges) {
if (n < 1 || edges == null) {
return 0;
}
UnionFind uf = new UnionFind(n);
for (int[] edge : edges) {
uf.union(edge[0], edge[1]);
}
Set<Integer> components = new HashSet<>();
for (int i = 0; i < n; ++i) {
components.add(uf.find(i));
}
return components.size();
}
class UnionFind {
int[] parent;
public UnionFind(int n) {
parent = new int[n];
for (int i = 0; i < n; ++i) {
parent[i] = i;
}
}
public int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
public void union(int x, int y) {
parent[find(x)] = parent[find(y)];
}
}
}
也可以像下面这样,首先假设每个节点各成一个component,那么起初总共有n 个components。然后边遍历edges边执行union操作,执行成功一次意味着有两个component连起来了,那么--componentCount即可。
class Solution {
public int countComponents(int n, int[][] edges) {
if (n < 1 || edges == null) {
return 0;
}
int[] parent = new int[n];
for (int i = 0; i < n; ++i) {
parent[i] = i;
}
int components = n;
for (int[] edge : edges) {
int xset = find(parent, edge[0]);
int yset = find(parent, edge[1]);
if (xset != yset) { // union two components
parent[xset] = yset;
--components;
}
}
return components;
}
public int find(int[] parent, int x) {
if (parent[x] != x) {
parent[x] = find(parent, parent[x]);
}
return parent[x];
}
}