并查集算法应用
通过Union对象来通过联通区域的个数
应用案例:leetcode-cn.com/problems/nu…
class Union{
int count;
int[] rank;
int[] parent;
public Union(char[][] grid){
count = 0;
int row = grid.length;
int col = grid[0].length;
rank = new int[row*col];
parent = new int[row*col];
for(int i=0; i<row; i++){
for(int j=0; j<col; j++){
if(grid[i][j] == '1'){
parent[i * col + j] = i * col + j;
count++;
}
rank[i * col + j] = 0;
}
}
}
public void union(int i, int j){
int ri = find(i);
int rj = find(j);
if(ri!=rj){
if(rank[ri]>rank[rj]){
parent[rj] = ri;
}else if(rank[ri]<rank[rj]){
parent[ri] = rj;
}else{
parent[rj] = ri;
rank[ri] += 1;
}
count--;
}
}
}
在初始化Union时,将每个点的parent设为本身,且存在点满足条件(在本例中,)时,应当递增Union对象的count属性。
在后续union的过程中,每当union一个点,执行count--操作。
经过这两步处理,count属性记录的就是图中的联通区域的个数,在本例中即是岛屿的个数。
通过Union对象来通过联通区域的个数
应用案例:leetcode-cn.com/problems/pa…
public int minimumEffortPath(int[][] heights) {
int m = heights.length;
int n = heights[0].length;
List<int[]> edges = new ArrayList<int[]>();
// 对图进行遍历
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int id = i * n + j;
// 上方
if (i > 0) {
edges.add(new int[]{id - n, id, Math.abs(heights[i][j] - heights[i - 1][j])});
}
// 左方
if (j > 0) {
edges.add(new int[]{id - 1, id, Math.abs(heights[i][j] - heights[i][j - 1])});
}
}
}
//根据集合中的绝对值之差 排序
Collections.sort(edges, new Comparator<int[]>() {
public int compare(int[] edge1, int[] edge2) {
return edge1[2] - edge2[2];
}
});
UnionFind uf = new UnionFind(m * n);
int ans = 0;
for (int[] edge : edges) {
int x = edge[0], y = edge[1], v = edge[2];
uf.unite(x, y);
if (uf.connected(0, m * n - 1)) {
ans = v;
break;
}
}
return ans;
}
在本例中,一条路径耗费的 体力值 是路径上相邻格子之间 高度差绝对值 的 最大值 决定的。求从左上角走到右下角的最小 体力消耗值 。
将两点的索引和体力值包装成数组,放入List中,根据体力值从小到大排序。从List中取出元素,联通数组中的两个点,然后判断此刻左上角和右下角是否联通,如果联通,则此时的体力值就是返回值。(从小到大排序,当某一刻联通时,该时刻的体力值就是该路径上的最大值)。