Skip to content

Commit 72494bf

Browse files
authored
Merge pull request #1023 from Hitesh4278/number-of-provinces
Added Solution for Number of Provinces - Issue No #968
2 parents 2e5a08c + 0dc0396 commit 72494bf

File tree

2 files changed

+342
-3
lines changed

2 files changed

+342
-3
lines changed

dsa-problems/leetcode-problems/0500-0599.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,10 @@ export const problems =[
275275
"solutionLink": "#"
276276
},
277277
{
278-
"problemName": "547. Friend Circles",
278+
"problemName": "547. Number of Provinces",
279279
"difficulty": "Medium",
280-
"leetCodeLink": "https://leetcode.com/problems/friend-circles",
281-
"solutionLink": "#"
280+
"leetCodeLink": "https://leetcode.com/problems/number-of-provinces/",
281+
"solutionLink": "/dsa-solutions/lc-solutions/0500-0599/number-of-provinces"
282282
},
283283
{
284284
"problemName": "548. Split Array with Equal Sum",
Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
---
2+
id: number-of-provinces
3+
title: Number of Provinces
4+
sidebar_label: 0547 - Number of Provinces
5+
tags:
6+
- Depth-First Search
7+
- Breadth-First Search
8+
- Union Find
9+
- Graph
10+
description: "This is a solution to the Number of Provincess problem on LeetCode."
11+
---
12+
13+
## Problem Description
14+
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.
15+
A province is a group of directly or indirectly connected cities and no other cities outside of the group.
16+
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.
17+
Return the total number of provinces.
18+
19+
### Examples
20+
21+
**Example 1:**
22+
![image](https://assets.leetcode.com/uploads/2020/12/24/graph1.jpg)
23+
```
24+
Input: isConnected = [[1,1,0],[1,1,0],[0,0,1]]
25+
Output: 2
26+
```
27+
28+
**Example 2:**
29+
![image](https://assets.leetcode.com/uploads/2020/12/24/graph2.jpg)
30+
```
31+
Input: isConnected = [[1,0,0],[0,1,0],[0,0,1]]
32+
Output: 3
33+
```
34+
35+
### Constraints
36+
- `1 <= n <= 200`
37+
- `n == isConnected.length`
38+
- `n == isConnected[i].length`
39+
- `isConnected[i][j] is 1 or 0.`
40+
- `isConnected[i][i] == 1`
41+
- `isConnected[i][j] == isConnected[j][i]`
42+
43+
## Solution for Number of Provinces
44+
45+
### Intuition ans Approach
46+
- To find the solution, we conceptualize the cities and the connections between them as a graph, where each city is a node and each direct connection is an edge. Now, the problem translates to finding the number of connected components in the graph. Each connected component will represent one province.
47+
48+
- To do this, we use Depth-First Search (DFS). Here's the intuition behind using DFS:
49+
50+
- We start with the first city and perform a DFS to mark all cities that are connected directly or indirectly to it. These cities form one province.
51+
- Once the DFS is completed, we look for the next city that hasn't been visited yet and perform a DFS from that city to find another province.
52+
- We repeat this process until all cities have been visited.
53+
- Each time we initiate a DFS from a new unvisited city, we know that we've found a new province, so we increment our province count. The DFS ensures that we navigate through all the cities within a province before moving on to the next one.
54+
- By doing the above steps using a vis (visited) list to keep track of which cities have been visited, we can effectively determine and count all the provinces.
55+
56+
<Tabs>
57+
<TabItem value="Solution" label="Solution">
58+
59+
#### Implementation
60+
61+
```jsx live
62+
function Solution() {
63+
function dfs(root, vis, adj) {
64+
vis[root] = 1;
65+
for (let val of adj[root]) {
66+
if (vis[val] === 0) {
67+
dfs(val, vis, adj);
68+
}
69+
}
70+
}
71+
72+
function findCircleNum(isConnected) {
73+
const n = isConnected.length;
74+
let cnt = 0;
75+
const vis = new Array(n + 1).fill(0);
76+
const adj = Array.from({ length: n + 1 }, () => []);
77+
78+
// Build adjacency list
79+
for (let i = 0; i < n; i++) {
80+
for (let j = 0; j < n; j++) {
81+
if (i !== j && isConnected[i][j] === 1) {
82+
adj[i + 1].push(j + 1);
83+
}
84+
}
85+
}
86+
87+
// Find all provinces
88+
for (let i = 1; i <= n; i++) {
89+
if (vis[i] === 0) {
90+
cnt++;
91+
dfs(i, vis, adj);
92+
}
93+
}
94+
95+
return cnt;
96+
}
97+
98+
99+
const input = [[1,1,0],[1,1,0],[0,0,1]]
100+
const output = findCircleNum(input);
101+
return (
102+
<div>
103+
<p>
104+
<b>Input: </b>{JSON.stringify(input)}
105+
</p>
106+
<p>
107+
<b>Output:</b> {output.toString()}
108+
</p>
109+
</div>
110+
);
111+
}
112+
```
113+
114+
### Code in Different Languages
115+
116+
<Tabs>
117+
<TabItem value="JavaScript" label="JavaScript">
118+
<SolutionAuthor name="@hiteshgahanolia"/>
119+
```javascript
120+
function dfs(root, vis, adj) {
121+
vis[root] = 1;
122+
for (let val of adj[root]) {
123+
if (vis[val] === 0) {
124+
dfs(val, vis, adj);
125+
}
126+
}
127+
}
128+
129+
function findCircleNum(isConnected) {
130+
const n = isConnected.length;
131+
let cnt = 0;
132+
const vis = new Array(n + 1).fill(0);
133+
const adj = Array.from({ length: n + 1 }, () => []);
134+
135+
// Build adjacency list
136+
for (let i = 0; i < n; i++) {
137+
for (let j = 0; j < n; j++) {
138+
if (i !== j && isConnected[i][j] === 1) {
139+
adj[i + 1].push(j + 1);
140+
}
141+
}
142+
}
143+
144+
// Find all provinces
145+
for (let i = 1; i <= n; i++) {
146+
if (vis[i] === 0) {
147+
cnt++;
148+
dfs(i, vis, adj);
149+
}
150+
}
151+
152+
return cnt;
153+
}
154+
155+
```
156+
</TabItem>
157+
<TabItem value="TypeScript" label="TypeScript">
158+
<SolutionAuthor name="@hiteshgahanolia"/>
159+
```typescript
160+
class Solution {
161+
dfs(root: number, vis: number[], adj: number[][]): void {
162+
vis[root] = 1;
163+
for (let val of adj[root]) {
164+
if (vis[val] === 0) {
165+
this.dfs(val, vis, adj);
166+
}
167+
}
168+
}
169+
170+
findCircleNum(isConnected: number[][]): number {
171+
const n = isConnected.length;
172+
let cnt = 0;
173+
const vis = new Array(n + 1).fill(0);
174+
const adj: number[][] = Array.from({ length: n + 1 }, () => []);
175+
176+
// Build adjacency list
177+
for (let i = 0; i < n; i++) {
178+
for (let j = 0; j < n; j++) {
179+
if (i !== j && isConnected[i][j] === 1) {
180+
adj[i + 1].push(j + 1);
181+
}
182+
}
183+
}
184+
185+
// Find all provinces
186+
for (let i = 1; i <= n; i++) {
187+
if (vis[i] === 0) {
188+
cnt++;
189+
this.dfs(i, vis, adj);
190+
}
191+
}
192+
193+
return cnt;
194+
}
195+
}
196+
197+
```
198+
</TabItem>
199+
<TabItem value="Python" label="Python">
200+
<SolutionAuthor name="@hiteshgahanolia"/>
201+
```python
202+
class Solution:
203+
def dfs(self, root, vis, adj):
204+
vis[root] = 1
205+
for val in adj[root]:
206+
if not vis[val]:
207+
self.dfs(val, vis, adj)
208+
209+
def findCircleNum(self, isConnected):
210+
n = len(isConnected)
211+
cnt = 0
212+
vis = [0] * (n + 1)
213+
adj = [[] for _ in range(n + 1)]
214+
215+
# Build adjacency list
216+
for i in range(n):
217+
for j in range(n):
218+
if i != j and isConnected[i][j] == 1:
219+
adj[i + 1].append(j + 1)
220+
221+
# Find all provinces
222+
for i in range(1, n + 1):
223+
if not vis[i]:
224+
cnt += 1
225+
self.dfs(i, vis, adj)
226+
227+
return cnt
228+
```
229+
</TabItem>
230+
<TabItem value="Java" label="Java">
231+
<SolutionAuthor name="@hiteshgahanolia"/>
232+
```java
233+
import java.util.*;
234+
235+
class Solution {
236+
public void dfs(int root, int[] vis, List<Integer>[] adj) {
237+
vis[root] = 1;
238+
for (int val : adj[root]) {
239+
if (vis[val] == 0) {
240+
dfs(val, vis, adj);
241+
}
242+
}
243+
}
244+
245+
public int findCircleNum(int[][] isConnected) {
246+
int n = isConnected.length;
247+
int cnt = 0;
248+
int[] vis = new int[n + 1];
249+
List<Integer>[] adj = new ArrayList[n + 1];
250+
251+
for (int i = 0; i <= n; i++) {
252+
adj[i] = new ArrayList<>();
253+
}
254+
255+
// Build adjacency list
256+
for (int i = 0; i < n; i++) {
257+
for (int j = 0; j < n; j++) {
258+
if (i != j && isConnected[i][j] == 1) {
259+
adj[i + 1].add(j + 1);
260+
}
261+
}
262+
}
263+
264+
// Find all provinces
265+
for (int i = 1; i <= n; i++) {
266+
if (vis[i] == 0) {
267+
cnt++;
268+
dfs(i, vis, adj);
269+
}
270+
}
271+
272+
return cnt;
273+
}
274+
}
275+
276+
```
277+
</TabItem>
278+
<TabItem value="C++" label="C++">
279+
<SolutionAuthor name="@hiteshgahanolia"/>
280+
```cpp
281+
class Solution {
282+
public:
283+
void dfs(int root, vector<int>& vis, vector<int> adj[]){
284+
285+
vis[root]=1;
286+
for (auto val : adj[root]){
287+
if(!vis[val]){
288+
dfs(val,vis,adj);
289+
}
290+
}
291+
}
292+
293+
int findCircleNum(vector<vector<int>>& isConnected) {
294+
295+
int n= isConnected.size();
296+
int cnt=0;
297+
vector<int> vis(n+1,0);
298+
vector<int> adj[n+1];
299+
for (int i=0; i<n; i++){
300+
for (int j=0; j<n; j++){
301+
if (i!=j && isConnected[i][j]){
302+
adj[i+1].push_back(j+1);
303+
}
304+
}
305+
}
306+
for (int i=1; i<=n; i++){
307+
if(!vis[i]){
308+
cnt++;
309+
dfs(i,vis,adj);
310+
}
311+
}
312+
return cnt;
313+
}
314+
};
315+
```
316+
</TabItem>
317+
</Tabs>
318+
319+
#### Complexity Analysis
320+
##### Time Complexity:
321+
- The time complexity of the algorithm is $O(N^2)$, where N is the number of vertices (or cities) in the graph. This complexity arises because the algorithm involves visiting every vertex once and, for each vertex, iterating through all possible adjacent vertices to explore the edges. In the worst-case scenario, this results in checking every entry in the isConnected matrix once, which has $(N^2)$ entries.
322+
323+
- The dfs function explores all connected vertices through recursive calls. Since each edge and vertex will only be visited once in the DFS traversal, the total number of operations performed will be related to the total number of vertices and edges. However, because the graph is represented by an N x N adjacency matrix and it must be fully inspected to discover all connections, the time is bounded by the size of the matrix $(N^2)$.
324+
325+
##### Space Complexity:
326+
The space complexity of the algorithm is $O(N)$, which comes from the following:
327+
- The recursion stack for DFS, which in the worst case, could store up to N frames if the graph is implemented as a linked structure such as a list of nodes (a path with all nodes connected end-to-end).
328+
- The vis visited array, which is a boolean array of length N used to track whether each vertex has been visited or not to prevent cycles during the DFS.
329+
- Given that N recursion calls could happen in a singly connected component spanning all the vertices, the space taken by the call stack should be considered in the final space complexity, merging it with the space taken by the array to $O(N)$.
330+
331+
</TabItem>
332+
</Tabs>
333+
334+
## References
335+
336+
- **LeetCode Problem**: [Number of Provinces](https://leetcode.com/problems/number-of-provinces/description/)
337+
338+
- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/number-of-provinces/solutions)
339+

0 commit comments

Comments
 (0)