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.
类似200 Number of Islands: http://www.jianshu.com/p/f834dbd46dd3
Solution1:Union Find
思路: Typical union find
1_a: routine
1_b: short version
Time Complexity: O(ElogV) ? Space Complexity: O(V)
Solution2:DFS (recursive)
思路: dfs visit,跳过已经visit的,记录遍历中visit的次数作为结果
Time Complexity: O(E+V) Space Complexity: O(E+V)
Solution3:DFS (stack)
思路: dfs visit,跳过已经visit的,记录遍历中visit的次数作为结果,思路同2,stack实现。
Time Complexity: O(E+V) Space Complexity: O(E+V)
Solution4:BFS (queue)
思路: dfs visit,跳过已经visit的,记录遍历中visit的次数作为结果,思路同。
实现同3,将stack改为queue即可。
Time Complexity: O(E+V) Space Complexity: O(E+V)
Solution1a Code:
class Solution {
class UF {
private int[] id;
private int[] sz; // for an id, the number of elements in that id
private int count; // number of sort of id
public UF(int n) {
this.id = new int[n];
this.sz = new int[n];
this.count = 0;
// init
for (int i = 0; i < n; i++) {
this.id[i] = i;
this.sz[i] = 1;
this.count++;
}
}
public void union(int p, int q) {
int p_root = find(p), q_root = find(q);
// weighted quick union
///*
if(p_root == q_root) return;
if (sz[p_root] < sz[q_root]) {
id[p_root] = q_root; sz[q_root] += sz[p_root];
} else {
id[q_root] = p_root; sz[p_root] += sz[q_root];
}
--count;
//*/
// regular
/*
if(p_root == q_root) return;
id[p_root] = q_root;
--count;
*/
}
public int find(int i) { // path compression
for (;i != id[i]; i = id[i])
id[i] = id[id[i]];
return i;
}
public boolean connected(int p, int q) {
int p_root = find(p);
int q_root = find(q);
if(p_root != q_root) return false;
else return true;
}
public int count() {
return this.count;
}
}
public int countComponents(int n, int[][] edges) {
UF uf = new UF(n);
for(int[] e : edges) {
int root1 = uf.find(e[0]);
int root2 = uf.find(e[1]);
if(root1 != root2) {
uf.union(root1, root2);
}
}
return uf.count();
}
}
class Solution {
public int countComponents(int n, int[][] edges) {
int[] roots = new int[n];
for(int i = 0; i < n; i++) roots[i] = i;
for(int[] e : edges) {
int root1 = find(roots, e[0]);
int root2 = find(roots, e[1]);
if(root1 != root2) {
roots[root1] = root2; // union
n--;
}
}
return n;
}
public int find(int[] roots, int id) {
while(roots[id] != id) {
roots[id] = roots[roots[id]]; // optional: path compression
id = roots[id];
}
return id;
}
}
Solution1b Code:
class Solution {
public int countComponents(int n, int[][] edges) {
int[] roots = new int[n];
for(int i = 0; i < n; i++) roots[i] = i;
for(int[] e : edges) {
int root1 = find(roots, e[0]);
int root2 = find(roots, e[1]);
if(root1 != root2) {
roots[root1] = root2; // union
n--;
}
}
return n;
}
public int find(int[] roots, int id) {
while(roots[id] != id) {
roots[id] = roots[roots[id]]; // optional: path compression
id = roots[id];
}
return id;
}
}
Solution2 Code:
public class Solution {
public int countComponents(int n, int[][] edges) {
if (n <= 1) {
return n;
}
// graph = adj_list init
List<List<Integer>> graph = new ArrayList<List<Integer>>();
for(int i = 0; i < n; i++) {
graph.add(new ArrayList<Integer>()); // LinkedList is also OK
}
// graph(adj_list) build
// i -> j node pairs
for (int i = 0; i < edges.length; i++) {
int pre = edges[i][0];
int post = edges[i][1];
graph.get(pre).add(post);
graph.get(post).add(pre);
}
boolean visited[] = new boolean[n];
int count = 0;
for(int i = 0; i < n; i++) {
if(!visited[i]) {
dfs(graph, i, visited);
count++;
}
}
return count;
}
private void dfs(List<List<Integer>> graph, int start, boolean[] visited) {
visited[start] = true;
for (int des : graph.get(start)) {
if(!visited[des]) {
dfs(graph, des, visited);
}
}
}
}
Solution3 Code:
public class Solution {
public int countComponents(int n, int[][] edges) {
if (n <= 1) {
return n;
}
// graph = adj_list init
List<List<Integer>> graph = new ArrayList<List<Integer>>();
for(int i = 0; i < n; i++) {
graph.add(new ArrayList<Integer>()); // LinkedList is also OK
}
// graph(adj_list) build
// i -> j node pairs
for (int i = 0; i < edges.length; i++) {
int pre = edges[i][0];
int post = edges[i][1];
graph.get(pre).add(post);
graph.get(post).add(pre);
}
boolean visited[] = new boolean[n];
int count = 0;
for(int i = 0; i < n; i++) {
if(!visited[i]) {
dfs(graph, i, visited);
count++;
}
}
return count;
}
private void dfs(List<List<Integer>> graph, int start, boolean[] visited) {
Deque<Integer> stack = new ArrayDeque<Integer>();
stack.push(start);
visited[start] = true;
while(!stack.isEmpty())
{
int from = stack.pop();
for(int des : graph.get(from)) {
if(visited[des]) continue;
stack.push(des);
visited[des] = true;
}
}
}
}
Solution4 Code:
public class Solution {
public int countComponents(int n, int[][] edges) {
if (n <= 1) {
return n;
}
// graph = adj_list init
List<List<Integer>> graph = new ArrayList<List<Integer>>();
for(int i = 0; i < n; i++) {
graph.add(new ArrayList<Integer>()); // LinkedList is also OK
}
// graph(adj_list) build
// i -> j node pairs
for (int i = 0; i < edges.length; i++) {
int pre = edges[i][0];
int post = edges[i][1];
graph.get(pre).add(post);
graph.get(post).add(pre);
}
boolean visited[] = new boolean[n];
int count = 0;
for(int i = 0; i < n; i++) {
if(!visited[i]) {
dfs(graph, i, visited);
count++;
}
}
return count;
}
private void dfs(List<List<Integer>> graph, int start, boolean[] visited) {
Queue<Integer> queue = new LinkedList<Integer>();
queue.offer(start);
visited[start] = true;
while(!queue.isEmpty())
{
int from = queue.poll();
for(int des : graph.get(from)) {
if(visited[des]) continue;
queue.offer(des);
visited[des] = true;
}
}
}
}