2023年4月19日,今天刷Leetcode的图论相关的知识(因为是才入手,所以懂的不是很多),遇到一题547.省份数量(实际上就是求解连通分支数),但是由于自己的数据结构和算法学的相当差,所以自己基本没有什么思路,参考题解给了3种方法:深度优先搜索、广度优先搜索和并查集,其中的并查集让我不太理解,其它两种自己还是有些许明白的。
1.深度优先搜索:用数组cities[n]来存储城市是否被访问,然后进行访问图的存储矩阵进行搜索,连同城市直接一搜到底,然后对访问的城市进行标记,然后对provinces++;
2.广度优先搜索:略
3.并查集:
先介绍一下定义:并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。
步骤1:初始化 把每个点所在集合初始化为其自身。
步骤2:查找 查找元素所在的集合,即根节点。
步骤3:合并 将两个元素所在的集合合并为一个集合。
Leetcode上面相应的例题是: 有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。 省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。返回矩阵中省份的数量。
相应的代码如下:
class Solution {
public:
int Find(vector<int>& parent, int index) {//进行查找,找到相应集合代表性元素,然后进行返回
if (parent[index] != index) {
parent[index] = Find(parent, parent[index]);
}
return parent[index];
}
void Union(vector<int>& parent, int index1, int index2) {//合并,将index1合并入index2中
parent[Find(parent, index1)] = Find(parent, index2);
}
int findCircleNum(vector<vector<int>>& isConnected) {
int cities = isConnected.size();
vector<int> parent(cities);
for (int i = 0; i < cities; i++) {//初始化
parent[i] = i;
}
for (int i = 0; i < cities; i++) {
for (int j = i + 1; j < cities; j++) {
if (isConnected[i][j] == 1) {
Union(parent, i, j);
}
}
}
int provinces = 0;
for (int i = 0; i < cities; i++) {
if (parent[i] == i) {
provinces++;
}
}
return provinces;
}
};
后续直接遍历遇到parent[i] = i的时候省份provinces++,最终就可以返回省份数量!!!