一,题目
二,分析
三,解法
四,参考
leetcode网站的题解参考
class Solution {
public int[] hitBricks(int[][] grid, int[][] hits) {
int R = grid.length, C = grid[0].length;
int[] dr = {1, 0, -1, 0};
int[] dc = {0, 1, 0, -1};
int[][] A = new int[R][C];
for (int r = 0; r < R; ++r)
A[r] = grid[r].clone();
for (int[] hit: hits)
A[hit[0]][hit[1]] = 0;
DSU dsu = new DSU(R*C + 1);
for (int r = 0; r < R; ++r) {
for (int c = 0; c < C; ++c) {
if (A[r][c] == 1) {
int i = r * C + c;
if (r == 0)
dsu.union(i, R*C);
if (r > 0 && A[r-1][c] == 1)
dsu.union(i, (r-1) *C + c);
if (c > 0 && A[r][c-1] == 1)
dsu.union(i, r * C + c-1);
}
}
}
int t = hits.length;
int[] ans = new int[t--];
while (t >= 0) {
int r = hits[t][0];
int c = hits[t][1];
int preRoof = dsu.top();
if (grid[r][c] == 0) {
t--;
} else {
int i = r * C + c;
for (int k = 0; k < 4; ++k) {
int nr = r + dr[k];
int nc = c + dc[k];
if (0 <= nr && nr < R && 0 <= nc && nc < C && A[nr][nc] == 1)
dsu.union(i, nr * C + nc);
}
if (r == 0)
dsu.union(i, R*C);
A[r][c] = 1;
ans[t--] = Math.max(0, dsu.top() - preRoof - 1);
}
}
return ans;
}
}
class DSU {
int[] parent;
int[] rank;
int[] sz;
public DSU(int N) {
parent = new int[N];
for (int i = 0; i < N; ++i)
parent[i] = i;
rank = new int[N];
sz = new int[N];
Arrays.fill(sz, 1);
}
//这里采用了路径压缩,在搜索的时候把所有经过的节点的parent都指向了根节点
public int find(int x) {
if (parent[x] != x) parent[x] = find(parent[x]);
return parent[x];
}
public void union(int x, int y) {
int xr = find(x), yr = find(y);
if (xr == yr) return;
//这里的交换操作使得yr永远是是权重(rank)小的那个
if (rank[xr] < rank[yr]) {
int tmp = yr;
yr = xr;
xr = tmp;
}
if (rank[xr] == rank[yr])
rank[xr]++;
//yr是权重(rank)小的那个
parent[yr] = xr;
sz[xr] += sz[yr];
}
public int size(int x) {
return sz[find(x)];
}
public int top() {
return size(sz.length - 1) - 1;
}
}