思路1
深度优先搜索
public int findCircleNum1(int[][] isConnected) {
int provinces = isConnected.length;
boolean[] visited = new boolean[provinces];
int circles = 0;
for (int i = 0; i < provinces; i++) {
if (!visited[i]) { // 在DFS中进行设置,设置为true的就已经连接到一个circle中了
dfs2(isConnected, visited, provinces, i); // DFS的作用是更改每一个城市是否放在circle中
circles++;
}
}
return circles;
}
public void dfs2(int[][] isConnected, boolean[] visited, int provinces, int i) {
for (int j = 0; j < provinces; j++) { // 注意这里j = 0而不是j = i+1
// visited[i] = true;
if (isConnected[i][j] == 1 && !visited[j]) {
visited[j] = true;
dfs2(isConnected, visited, provinces, j);
}
}
}
思路2
广度优先搜索
【注】入队列时标记已经访问过在LeetCode平台上用时较少
public int findCircleNum(int[][] isConnected) {
int ret = 0;
Queue<Integer> q = new LinkedList<Integer>();
int n = isConnected.length;
int[] read = new int[n];
for (int i = 0; i < n; i++)
{
if (read[i] == 0)
{
read[i] = 1; // 入队列时标记已经访问过
q.offer(i);
ret++;
while (!q.isEmpty())
{
int t = q.poll();
// read[t] = 1; 出队列时标记已经访问过
for (int j = i+1; j < n; j++)
{
if (isConnected[t][j] == 1 && read[j] == 0)
{
read[j] = 1; // 入队列时标记已经访问过
q.offer(j);
}
}
}
}
}
return ret;
}
思路3
并查集
public int findCircleNum3(int[][] isConnected) {
int provinces = isConnected.length;
int[] parent = new int[provinces];
for (int i = 0; i < provinces; i++) {
parent[i] = i; // 将父亲设置为自己
}
for (int i = 0; i < provinces; i++) {
for (int j = i + 1; j < provinces; j++) {
if (isConnected[i][j] == 1) {
union(parent, i, j); // i和j合并
}
}
}
int circles = 0;
for (int i = 0; i < provinces; i++) {
if (parent[i] == i) {
circles++;
}
}
return circles;
}
public void union(int[] parent, int index1, int index2) {
parent[find(parent, index1)] = find(parent, index2); // index1的父节点是index2的父亲
}
public int find(int[] parent, int index) {
while (parent[index] != index)
index = parent[index];
return index;
}