LeetCodee

547. Number of Provinces

Jump to Solution: Python Java C++ JavaScript C#

Problem Description

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 1:

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

Example 2:

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

Constraints:

  • 1 <= n <= 200
  • n == isConnected.length
  • n == isConnected[i].length
  • isConnected[i][j] is 1 or 0
  • isConnected[i][i] == 1
  • isConnected[i][j] == isConnected[j][i]

Solution

Python Solution

class Solution:
    def findCircleNum(self, isConnected: List[List[int]]) -> int:
        n = len(isConnected)
        visited = set()
        provinces = 0
        
        def dfs(city: int) -> None:
            visited.add(city)
            for neighbor in range(n):
                if isConnected[city][neighbor] == 1 and neighbor not in visited:
                    dfs(neighbor)
        
        for city in range(n):
            if city not in visited:
                dfs(city)
                provinces += 1
        
        return provinces

Time Complexity: O(n²)

Where n is the number of cities. We need to visit each city and check its connections.

Space Complexity: O(n)

For the visited set and recursion stack.

Java Solution

class Solution {
    private void dfs(int[][] isConnected, boolean[] visited, int city) {
        visited[city] = true;
        for (int neighbor = 0; neighbor < isConnected.length; neighbor++) {
            if (isConnected[city][neighbor] == 1 && !visited[neighbor]) {
                dfs(isConnected, visited, neighbor);
            }
        }
    }
    
    public int findCircleNum(int[][] isConnected) {
        int n = isConnected.length;
        boolean[] visited = new boolean[n];
        int provinces = 0;
        
        for (int city = 0; city < n; city++) {
            if (!visited[city]) {
                dfs(isConnected, visited, city);
                provinces++;
            }
        }
        
        return provinces;
    }
}

Time Complexity: O(n²)

Where n is the number of cities. We need to visit each city and check its connections.

Space Complexity: O(n)

For the visited array and recursion stack.

C++ Solution

class Solution {
private:
    void dfs(vector>& isConnected, vector& visited, int city) {
        visited[city] = true;
        for (int neighbor = 0; neighbor < isConnected.size(); neighbor++) {
            if (isConnected[city][neighbor] == 1 && !visited[neighbor]) {
                dfs(isConnected, visited, neighbor);
            }
        }
    }
    
public:
    int findCircleNum(vector>& isConnected) {
        int n = isConnected.size();
        vector visited(n, false);
        int provinces = 0;
        
        for (int city = 0; city < n; city++) {
            if (!visited[city]) {
                dfs(isConnected, visited, city);
                provinces++;
            }
        }
        
        return provinces;
    }
};

Time Complexity: O(n²)

Where n is the number of cities. We need to visit each city and check its connections.

Space Complexity: O(n)

For the visited vector and recursion stack.

JavaScript Solution

/**
 * @param {number[][]} isConnected
 * @return {number}
 */
var findCircleNum = function(isConnected) {
    const n = isConnected.length;
    const visited = new Set();
    let provinces = 0;
    
    const dfs = (city) => {
        visited.add(city);
        for (let neighbor = 0; neighbor < n; neighbor++) {
            if (isConnected[city][neighbor] === 1 && !visited.has(neighbor)) {
                dfs(neighbor);
            }
        }
    };
    
    for (let city = 0; city < n; city++) {
        if (!visited.has(city)) {
            dfs(city);
            provinces++;
        }
    }
    
    return provinces;
};

Time Complexity: O(n²)

Where n is the number of cities. We need to visit each city and check its connections.

Space Complexity: O(n)

For the visited set and recursion stack.

C# Solution

public class Solution {
    private void DFS(int[][] isConnected, bool[] visited, int city) {
        visited[city] = true;
        for (int neighbor = 0; neighbor < isConnected.Length; neighbor++) {
            if (isConnected[city][neighbor] == 1 && !visited[neighbor]) {
                DFS(isConnected, visited, neighbor);
            }
        }
    }
    
    public int FindCircleNum(int[][] isConnected) {
        int n = isConnected.Length;
        bool[] visited = new bool[n];
        int provinces = 0;
        
        for (int city = 0; city < n; city++) {
            if (!visited[city]) {
                DFS(isConnected, visited, city);
                provinces++;
            }
        }
        
        return provinces;
    }
}

Time Complexity: O(n²)

Where n is the number of cities. We need to visit each city and check its connections.

Space Complexity: O(n)

For the visited array and recursion stack.

Approach Explanation

The solution uses Depth-First Search (DFS) to find connected components:

  1. Key Insights:
    • Graph representation
    • Connected components
    • DFS traversal
    • Component counting
  2. Algorithm Steps:
    • Initialize visited
    • DFS each unvisited
    • Mark connected
    • Count provinces

Implementation Details:

  • Adjacency matrix
  • Visited tracking
  • Recursive DFS
  • Province counting

Optimization Insights:

  • Matrix symmetry
  • Early termination
  • Space efficiency
  • Visit tracking

Edge Cases:

  • Single city
  • All connected
  • No connections
  • Diagonal elements