LeetCode #323: Number of Connected Components in an Undirected Graph
https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/description/
This problem can be solved using the Union-Find algorithm. We can use two arrays, par
and rank
to keep track of the parent and the rank of each node, respectively. Initially, each node will have itself as its parent, and its rank will be set to 1.
We will then define two functions: find
and union
. The find
function will find the root parent of a given node. It will start from the given node and traverse the parent array until it reaches a node whose parent is itself. The function also applies the path compression optimization to reduce the height of the tree.
The union
function will union two nodes if they are not already connected. First, it will find the root parents of both nodes using the find
function. If both nodes have the same root parent, then they are already connected, and we can return 0. Otherwise, we will compare the ranks of the root parents and connect the smaller rank tree to the larger rank tree. Finally, we will update the rank of the larger rank tree to be the sum of the ranks of both trees.
We can iterate through the list of edges and call the union
function on each pair of nodes. Each time a new union is made, we will decrement the count of the number of components. The final answer will be the count of the number of remaining nodes.
- Initialize
par
andrank
arrays where each node has itself as its parent and a rank of 1. - Define the
find
function that will find the root parent of a given node using path compression optimization. - Define the
union
function that will union two nodes if they are not already connected. It will use thefind
function to find the root parents of the nodes and connect the smaller rank tree to the larger rank tree. It will also update the rank of the larger rank tree. - Iterate through the list of edges and call the
union
function on each pair of nodes. Decrement the count of the number of components each time a new union is made. - Return the count of the number of remaining nodes.
Here is the solution in python3:
class Solution:
def countComponents(self, n: int, edges: List[List[int]]) -> int:
par = [i for i in range(n)]
rank = [1] * n
def find(n1):
res = n1
while res != par[res]:
par[res] = par[par[res]]
res = par[res]
return res
def union(n1, n2):
p1, p2 = find(n1), find(n2)
if p1 == p2:
return 0
if rank[p2] > rank[p1]:
par[p1] = p2
rank[p2] += rank[p1]
else:
par[p2] = p1
rank[p1] += rank[p2]
return 1
for n1, n2 in edges:
n -= union(n1, n2)
return n
Time Complexity
The time complexity of both DFS and BFS is O(V + E), where V is the number of vertices and E is the number of edges in the graph. In the worst case, we would need to visit every vertex and every edge in the graph.
Space Complexity
The space complexity of both DFS and BFS is O(V), where V is the number of vertices in the graph. This is because we need to maintain a visited set and a queue or stack for the traversal, both of which can have at most V elements.