Skip to content

Commit

Permalink
feat: update solutions to lc problem: No.0547
Browse files Browse the repository at this point in the history
No.0547.Number of Provinces
  • Loading branch information
yanglbme committed Jan 20, 2025
1 parent 66418a9 commit d26fdb1
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 27 deletions.
17 changes: 7 additions & 10 deletions solution/0500-0599/0547.Number of Provinces/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ tags:

### 方法一:DFS

我们创建一个数组 $vis$,用于记录每个城市是否被访问过。
我们创建一个数组 $\textit{vis}$,用于记录每个城市是否被访问过。

接下来,遍历每个城市 $i$,如果该城市未被访问过,则从该城市开始深度优先搜索,通过矩阵 $isConnected$ 得到与该城市直接相连的城市有哪些,这些城市和该城市属于同一个省,然后对这些城市继续深度优先搜索,直到同一个省的所有城市都被访问到,即可得到一个省,将答案 $ans$ 加 $1$,然后遍历下一个未被访问过的城市,直到遍历完所有的城市。
接下来,遍历每个城市 $i$,如果该城市未被访问过,则从该城市开始深度优先搜索,通过矩阵 $\textit{isConnected}$ 得到与该城市直接相连的城市有哪些,这些城市和该城市属于同一个省,然后对这些城市继续深度优先搜索,直到同一个省的所有城市都被访问到,即可得到一个省,将答案 $\textit{ans}$ 加 $1$,然后遍历下一个未被访问过的城市,直到遍历完所有的城市。

最后返回答案即可。

Expand Down Expand Up @@ -141,7 +141,7 @@ public:
int ans = 0;
bool vis[n];
memset(vis, false, sizeof(vis));
function<void(int)> dfs = [&](int i) {
auto dfs = [&](this auto&& dfs, int i) -> void {
vis[i] = true;
for (int j = 0; j < n; ++j) {
if (!vis[j] && isConnected[i][j]) {
Expand Down Expand Up @@ -250,11 +250,11 @@ impl Solution {

我们也可以用并查集维护每个连通分量,初始时,每个城市都属于不同的连通分量,所以省份数量为 $n$。

接下来,遍历矩阵 $isConnected$,如果两个城市 $(i, j)$ 之间有相连关系,并且处于两个不同的连通分量,则它们将被合并成为一个连通分量,然后将省份数量减去 $1$。
接下来,遍历矩阵 $\textit{isConnected}$,如果两个城市 $(i, j)$ 之间有相连关系,并且处于两个不同的连通分量,则它们将被合并成为一个连通分量,然后将省份数量减去 $1$。

最后返回省份数量即可。

时间复杂度 $O(n^2 \times \alpha(n))$,空间复杂度 $O(n)$。其中 $n$ 是城市的数量,而 $\alpha$ 是阿克曼函数的反函数,在渐进意义下 $\alpha(n)$ 可以认为是一个很小的常数
时间复杂度 $O(n^2 \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是城市的数量,而 $\log n$ 是并查集的路径压缩的时间复杂度

<!-- tabs:start -->

Expand Down Expand Up @@ -326,7 +326,7 @@ public:
int n = isConnected.size();
int p[n];
iota(p, p + n, 0);
function<int(int)> find = [&](int x) -> int {
auto find = [&](this auto&& find, int x) -> int {
if (p[x] != x) {
p[x] = find(p[x]);
}
Expand Down Expand Up @@ -386,10 +386,7 @@ func findCircleNum(isConnected [][]int) (ans int) {
```ts
function findCircleNum(isConnected: number[][]): number {
const n = isConnected.length;
const p: number[] = new Array(n);
for (let i = 0; i < n; ++i) {
p[i] = i;
}
const p: number[] = Array.from({ length: n }, (_, i) => i);
const find = (x: number): number => {
if (p[x] !== x) {
p[x] = find(p[x]);
Expand Down
29 changes: 21 additions & 8 deletions solution/0500-0599/0547.Number of Provinces/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,15 @@ tags:

<!-- solution:start -->

### Solution 1
### Solution 1: DFS

We create an array $\textit{vis}$ to record whether each city has been visited.

Next, we traverse each city $i$. If the city has not been visited, we start a depth-first search from that city. Using the matrix $\textit{isConnected}$, we find the cities directly connected to this city. These cities and the current city belong to the same province. We continue the depth-first search for these cities until all cities in the same province have been visited. This counts as one province, so we increment the answer $\textit{ans}$ by $1$. Then, we move to the next unvisited city and repeat the process until all cities have been traversed.

Finally, return the answer.

The time complexity is $O(n^2)$, and the space complexity is $O(n)$. Here, $n$ is the number of cities.

<!-- tabs:start -->

Expand Down Expand Up @@ -127,7 +135,7 @@ public:
int ans = 0;
bool vis[n];
memset(vis, false, sizeof(vis));
function<void(int)> dfs = [&](int i) {
auto dfs = [&](this auto&& dfs, int i) -> void {
vis[i] = true;
for (int j = 0; j < n; ++j) {
if (!vis[j] && isConnected[i][j]) {
Expand Down Expand Up @@ -232,7 +240,15 @@ impl Solution {

<!-- solution:start -->

### Solution 2
### Solution 2: Union-Find

We can also use the union-find data structure to maintain each connected component. Initially, each city belongs to a different connected component, so the number of provinces is $n$.

Next, we traverse the matrix $\textit{isConnected}$. If there is a connection between two cities $(i, j)$ and they belong to two different connected components, they will be merged into one connected component, and the number of provinces is decremented by $1$.

Finally, return the number of provinces.

The time complexity is $O(n^2 \times \log n)$, and the space complexity is $O(n)$. Here, $n$ is the number of cities, and $\log n$ is the time complexity of path compression in the union-find data structure.

<!-- tabs:start -->

Expand Down Expand Up @@ -304,7 +320,7 @@ public:
int n = isConnected.size();
int p[n];
iota(p, p + n, 0);
function<int(int)> find = [&](int x) -> int {
auto find = [&](this auto&& find, int x) -> int {
if (p[x] != x) {
p[x] = find(p[x]);
}
Expand Down Expand Up @@ -364,10 +380,7 @@ func findCircleNum(isConnected [][]int) (ans int) {
```ts
function findCircleNum(isConnected: number[][]): number {
const n = isConnected.length;
const p: number[] = new Array(n);
for (let i = 0; i < n; ++i) {
p[i] = i;
}
const p: number[] = Array.from({ length: n }, (_, i) => i);
const find = (x: number): number => {
if (p[x] !== x) {
p[x] = find(p[x]);
Expand Down
4 changes: 2 additions & 2 deletions solution/0500-0599/0547.Number of Provinces/Solution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Solution {
int ans = 0;
bool vis[n];
memset(vis, false, sizeof(vis));
function<void(int)> dfs = [&](int i) {
auto dfs = [&](this auto&& dfs, int i) -> void {
vis[i] = true;
for (int j = 0; j < n; ++j) {
if (!vis[j] && isConnected[i][j]) {
Expand All @@ -21,4 +21,4 @@ class Solution {
}
return ans;
}
};
};
2 changes: 1 addition & 1 deletion solution/0500-0599/0547.Number of Provinces/Solution.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function findCircleNum(isConnected: number[][]): number {
const n = isConnected.length;
const vis: boolean[] = new Array(n).fill(false);
const vis: boolean[] = Array(n).fill(false);
const dfs = (i: number) => {
vis[i] = true;
for (let j = 0; j < n; ++j) {
Expand Down
4 changes: 2 additions & 2 deletions solution/0500-0599/0547.Number of Provinces/Solution2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Solution {
int n = isConnected.size();
int p[n];
iota(p, p + n, 0);
function<int(int)> find = [&](int x) -> int {
auto find = [&](this auto&& find, int x) -> int {
if (p[x] != x) {
p[x] = find(p[x]);
}
Expand All @@ -24,4 +24,4 @@ class Solution {
}
return ans;
}
};
};
5 changes: 1 addition & 4 deletions solution/0500-0599/0547.Number of Provinces/Solution2.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
function findCircleNum(isConnected: number[][]): number {
const n = isConnected.length;
const p: number[] = new Array(n);
for (let i = 0; i < n; ++i) {
p[i] = i;
}
const p: number[] = Array.from({ length: n }, (_, i) => i);
const find = (x: number): number => {
if (p[x] !== x) {
p[x] = find(p[x]);
Expand Down

0 comments on commit d26fdb1

Please sign in to comment.