Sale: Get 60% Off on all Pro Plans. Buy Now

Number of Provinces

Medium DFS

Problem

Given an n x n matrix isConnected where isConnected[i][j] = 1 if the ith city and the jth city are directly connected, and 0 otherwise, return the total number of provinces (groups of directly or indirectly connected cities).

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

Example

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

The cities 0 and 1 are directly connected, forming one province. City 2 is isolated, forming a second province. The DFS starts at city 0, marks city 1 as visited through the connection, and completes the first province. Then it moves to city 2, which is unvisited, marking the second province. The total count is 2.

Approach

Straightforward Solution

A brute-force approach would check every pair of cities and attempt to group them, but without efficient traversal, this leads to redundant checks and higher complexity.

Core Observation

The problem reduces to counting connected components in an undirected graph represented by an adjacency matrix. Each city is a node, and edges exist where isConnected[i][j] == 1.

Path to Optimal

Preview

Recognizing the problem as connected components counting suggests graph traversal algorithms. DFS or BFS can explore all nodes reachable from a starting node, marking them visited…

Full step-by-step walkthrough on Pro

Optimal Approach

Preview

Iterate over each city. If it is unvisited, increment the province count and perform a DFS to mark all cities connected to it as visited…

Full step-by-step walkthrough on Pro

Want the full reasoning chain?

Unlock the complete walkthrough, line-by-line analysis, and recall drill.

Unlock Pro

Time

O(n^2)

The adjacency matrix has n^2 entries. The DFS explores each node and its neighbors once, resulting in O(n^2) time since each edge is checked via the matrix.

Space

O(n)

The auxiliary space is O(n) for the recursion stack in the worst case and the visited set storing up to n nodes.

Pattern Spotlight

DFS (Connected Components in Graph)

When counting groups of connected nodes in an undirected graph, use DFS to explore and mark all nodes in a component starting from any unvisited node, incrementing the count each time a new unvisited node is found.

Solution

Python
1class Solution:
2 def findCircleNum(self, isConnected: List[List[int]]) -> int:
3 n = len(isConnected)
4 seen = set()
5
6 def dfs(i):
7 for j in range(n):
8 if isConnected[i][j] == 1 and j not in seen:
9 seen.add(j)
10 dfs(j)
11
12 provinces = 0
13 for i in range(n):
14 if i not in seen:
15 provinces += 1
16 seen.add(i)
17 dfs(i)
18
19 return provinces

Step-by-Step Solution

1

Initialize Variables and Define DFS Traversal

3n = len(isConnected)
4seen = set()
6def dfs(i):
7 for j in range(n):
8 if isConnected[i][j] == 1 and j not in seen:
9 seen.add(j)
10 dfs(j)

Objective

To prepare the data structures needed for traversal and define the recursive DFS function to explore connected cities.

Key Insight

Storing visited cities in a set prevents revisiting and infinite loops. The DFS function systematically explores all neighbors of a city, recursively marking connected cities as visited. This encapsulates the core traversal logic, enabling efficient connected component detection.

Interview Quick-Check

Core Logic

The DFS function recursively visits all cities connected to the current city, marking them visited to avoid repeated processing.

State & Boundaries

The visited set tracks which cities have been explored, ensuring each city is processed once.

Common Pitfalls & Bugs

Forgetting to add a city to the visited set before recursive DFS calls can cause infinite recursion or repeated visits.

2

Count Provinces by Iterating Over Cities and Invoking DFS

To iterate through all cities, identify unvisited ones, increment the province count, and trigger DFS to mark all connected cities.

3

Return the Total Number of Provinces

To output the final count of provinces after all cities have been processed.

2 more steps with full analysis available on Pro.

Line Analysis

This solution has 3 Critical lines interviewers watch for.

Line 8 Critical
if isConnected[i][j] == 1 and j not in seen:

Check if the neighbor city is connected and unvisited.

This conditional is critical because it ensures the DFS only explores valid, unvisited neighbors, preventing cycles and redundant traversals.

Line 9 Critical
seen.add(j)

Mark the neighbor city as visited.

Marking a city as visited before recursive calls is essential to avoid revisiting the same city multiple times, which would cause infinite recursion or incorrect province counts.

Line 16 Critical
seen.add(i)

Mark the current city as visited before DFS.

Adding the city to visited before DFS is critical to avoid infinite recursion and to correctly identify the province's extent.

Full line-by-line criticality + rationale for all 14 lines available on Pro.

Test Your Understanding

Why does performing a DFS from each unvisited city correctly count the number of provinces?

See the answer with Pro.

Related Problems

DFS pattern

Don't just read it. Drill it.

Reconstruct Number of Provinces from memory until it sticks. AlgoDrill blanks out key lines and makes you fill them back in, step by step.

Unlock the Number of Provinces drill

or drill a free problem