LeetCode 547. Number of Provinces

Post by ailswan Jul. 03, 2024

547. Number of Provinces

Problem Statement

link: LeetCode.cn LeetCode There are n cities. Some of them are connected, while some are not. If city a is connected directly with city b, and city b is connected directly with city c, then city a is connected indirectly with city c.

A province is a group of directly or indirectly connected cities and no other cities outside of the group.

You are given an n x n matrix isConnected where isConnected[i][j] = 1 if the ith city and the jth city are directly connected, and isConnected[i][j] = 0 otherwise.

Return the total number of provinces.

Example:

Input: isConnected = [[1,1,0],[1,1,0],[0,0,1]] Output: 2

Input: isConnected = [[1,0,0],[0,1,0],[0,0,1]] Output: 3

Solution Approach

The solution can be approached using Depth-First Search (DFS), Breadth-First Search (BFS), or Union-Find to traverse the graph represented by the adjacency matrix and count the number of connected components or provinces.

Algorithm

  1. Depth-First Search (DFS): Traverse the graph using DFS to mark all cities connected to a starting city as visited, and count each DFS initiation as a new province.
  2. Breadth-First Search (BFS): Use a queue to perform BFS, marking connected cities as visited, and count each BFS initiation as a new province.
  3. Union-Find: Utilize the Union-Find data structure to merge sets of connected cities and count the number of unique sets to determine the number of provinces.

Implement

    class Solution:
    def findCircleNum(self, isConnected):
        def dfs(i):
            for j in range(len(isConnected)):
                if isConnected[i][j] == 1 and not visited[j]:
                    visited[j] = True
                    dfs(j)

        visited = [False] * len(isConnected)
        count = 0

        for i in range(len(isConnected)):
            if not visited[i]:
                dfs(i)
                count += 1

        return count

class Solution:
    def findCircleNum(self, isConnected):
        visited = [False] * len(isConnected)
        queue = deque()
        count = 0

        for i in range(len(isConnected)):
            if not visited[i]:
                queue.append(i)
                while queue:
                    curr = queue.popleft()
                    visited[curr] = True
                    for j in range(len(isConnected)):
                        if isConnected[curr][j] == 1 and not visited[j]:
                            queue.append(j)
                count += 1

        return count



class UnionFind:
    def __init__(self, n):
        self.parents = list(range(n))
        self.groupNum = n

    def find(self, node):
        while node != self.parents[node]:
            self.parents[node] = self.parents[self.parents[node]]  # Path compression
            node = self.parents[node]
        return node

    def union(self, x, y):
        xParent = self.find(x)
        yParent = self.find(y)
        if xParent != yParent:
            self.parents[yParent] = xParent
            self.groupNum -= 1

    def getGroupNum(self):
        return self.groupNum

class Solution:
    def findCircleNum(self, isConnected):
        n = len(isConnected)
        unionFind = UnionFind(n)

        for i in range(n):
            for j in range(i + 1, n):
                if isConnected[i][j] == 1:
                    unionFind.union(i, j)

        return unionFind.getGroupNum()