题目:
力扣https://leetcode.cn/problems/bLyHh0/思路:
动态连通性算法API模板
init | 初始化连通数组(存储头索引),初始化加权数组(存储集合size) |
union | 连通 |
find | 递归找头索引 边界条件(如果头索引=自己的索引返回) |
connected | 判断是否连通 |
count | 连通分量数量 初始化为n,每union一次-1 |
初始化连通数组source值为自己的索引,初始化加权数组size值为1,初始化连通分量为n
遍历传入的二维数组isConnected,第二层遍历不需要遍历自己所以j初始值为i+1。
判断是否连通,如果未连通,调用union方法。
union实现细节:获取需要连通的i,j的头索引,比较size谁大(小的连大的,引入加权数组是一种优化,在leetcode的测试用例中不是很明显,比较适用于大数据量的情况),更新小头索引和大头size,最后连通分量-1
对于互相连接的这种情况,参数描述的情形是
实际生成的是
不存在多对多的连接情况,注意这一点就可以理解代码的逻辑了
题解:
package leetcode.May;
import java.util.List;
/**
* @description:
* 有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。
* 省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。
* 给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。
* 返回矩阵中 省份 的数量。
* 来源:力扣(LeetCode)
* @author: qiangyuecheng
* @date: 2022/5/19 16:25
*/
public class MapConnectivity {
int count;
int [] source ;
int [] size;
/**
* init 初始化
* union 连接
* find 找头
* connected 判断连接
* source 源
* view 加权
*/
public int findCircleNum(int[][] isConnected) {
int n = isConnected.length;
//初始化
init(n);
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
if(isConnected[i][j]==1){
//连接
union(i,j);
}
}
}
return count;
}
public void init(int n){
source = new int[n];
size = new int[n];
for (int i = 0; i < n; i++) {
source[i] = i;
size[i] = 1;
}
count = n;
}
public void union(int i,int j){
int headI = find(i);
int headJ = find(j);
if(headI!=headJ){
if(size[headI]>size[headJ]){
source[headJ] = headI;
size[headI]+=headJ;
}else {
source[headI] = headJ;
size[headJ]+=headI;
}
count--;
}
}
public int find(int index){
int head = source[index];
if(head==index){
return head;
}
return find(head);
}
public boolean connected(int i,int j){
return find(i)==find(j);
}
public static void main(String[] args) {
MapConnectivity mapConnectivity = new MapConnectivity();
//int [][] a = {{1,1,0},{1,1,0},{0,0,1}};
int [][] a = {{1,1,1},{1,1,1},{1,1,1}};
System.out.printf(""+ mapConnectivity.findCircleNum(a));
}
}