803. 打砖块
有一个 m x n 的二元网格 grid ,其中 1 表示砖块,0 表示空白。砖块 稳定(不会掉落)的前提是:
一块砖直接连接到网格的顶部,或者
至少有一块相邻(4 个方向之一)砖块 稳定 不会掉落时
给你一个数组 hits ,这是需要依次消除砖块的位置。每当消除 hits[i] = (rowi, coli) 位置上的砖块时,对应位置的砖块(若存在)会消失,然后其他的砖块可能因为这一消除操作而 掉落 。一旦砖块掉落,它会 立即 从网格 grid 中消失(即,它不会落在其他稳定的砖块上)。
返回一个数组 result ,其中 result[i] 表示第 i 次消除操作对应掉落的砖块数目。
注意,消除可能指向是没有砖块的空白位置,如果发生这种情况,则没有砖块掉落。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/bricks-falling-when-hit
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
private int[][] directions = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
public int[] hitBricks(int[][] grid, int[][] hits) {
for (int[] hit : hits) {
if (grid[hit[0]][hit[1]] == 1) {
grid[hit[0]][hit[1]] = 2;
}
}
UnionSet unionSet = new UnionSet(grid);
for (int i = 0; i < grid.length; ++i) {
for (int j = 0; j < grid[0].length; ++j) {
if (grid[i][j] == 1) {
for (int k = 0; k < directions.length; ++k) {
int x = i + directions[k][0];
int y = j + directions[k][1];
if (x >= 0 && x < grid.length && y >= 0 && y < grid[0].length && grid[x][y] == 1) {
unionSet.merge(new int[]{x, y}, new int[]{i, j});
}
}
}
}
}
int[] ans = new int[hits.length];
int total = unionSet.getTotal();
for (int i = hits.length - 1; i >= 0; --i) {
if (grid[hits[i][0]][hits[i][1]] == 2) {
unionSet.set(hits[i]);
for (int k = 0; k < directions.length; ++k) {
int x = hits[i][0] + directions[k][0];
int y = hits[i][1] + directions[k][1];
if (x >= 0 && x < grid.length && y >= 0 && y < grid[0].length && grid[x][y] == 1) {
unionSet.merge(new int[]{x, y}, hits[i]);
}
}
int newTotal = unionSet.getTotal();
if (newTotal != total) {
ans[i] = newTotal - total - 1;
}
total = newTotal;
}
}
return ans;
}
}
class UnionSet {
/**
* 图
*/
private int[][] grid;
/**
* 连通块父节点
*/
private int[] parent;
/**
* 连通块内1的个数
*/
private int[] size;
/**
* 连通块是否在墙上
*/
private boolean[] onWalls;
/**
* 在墙上的总数
*/
private int total;
public int[] convertIntToCoordinate(int x) {
return new int[]{x / grid[0].length, x % grid[0].length};
}
public int convertCoordinateToInt(int[] coordinate) {
return coordinate[0] * grid[0].length + coordinate[1];
}
public void set(int[] coordinate) {
size[convertCoordinateToInt(coordinate)] = 1;
grid[coordinate[0]][coordinate[1]] = 1;
if (coordinate[0] == 0) {
onWalls[convertCoordinateToInt(coordinate)] = true;
total++;
}
}
public int getTotal() {
return total;
}
public UnionSet(int[][] grid) {
int n = grid.length * grid[0].length;
this.grid = grid;
this.parent = new int[n];
this.onWalls = new boolean[n];
for (int i = 0; i < n; ++i) {
parent[i] = i;
}
this.size = new int[n];
this.total = 0;
for (int i = 0; i < grid.length; ++i) {
for (int j = 0; j < grid[0].length; ++j) {
if (grid[i][j] == 1) {
int x = convertCoordinateToInt(new int[]{i, j});
size[x] = 1;
if (i == 0) {
onWalls[x] = true;
total++;
}
}
}
}
}
private int find(int x) {
int f = parent[x];
if (x == f) {
return f;
}
f = find(f);
parent[x] = f;
return f;
}
public void merge(int[] c1, int[] c2) {
int a = convertCoordinateToInt(c1);
int b = convertCoordinateToInt(c2);
int f1 = find(a);
int f2 = find(b);
if (f1 != f2) {
int s1 = size[f1];
int s2 = size[f2];
boolean onWall = onWalls[f1] | onWalls[f2];
if (s1 < s2) {
parent[f1] = f2;
if (onWall) {
if (!onWalls[f1]) {
total += size[f1];
} else if (!onWalls[f2]) {
total += size[f2];
}
}
size[f2] += size[f1];
onWalls[f2] = onWall;
size[f1] = 0;
} else {
parent[f2] = f1;
if (onWall) {
if (!onWalls[f1]) {
total += size[f1];
} else if (!onWalls[f2]) {
total += size[f2];
}
}
size[f1] += size[f2];
onWalls[f1] = onWall;
size[f2] = 0;
}
}
}
}
心之所向,素履以往 生如逆旅,一苇以航

浙公网安备 33010602011771号