website/content/ChapterFour/0800~0899/0803.Bricks-Falling-When-Hit.md
We have a grid of 1s and 0s; the 1s in a cell represent bricks. A brick will not drop if and only if it is directly connected to the top of the grid, or at least one of its (4-way) adjacent bricks will not drop.
We will do some erasures sequentially. Each time we want to do the erasure at the location (i, j), the brick (if it exists) on that location will disappear, and then some other bricks may drop because of that erasure.
Return an array representing the number of bricks that will drop after each erasure in sequence.
Example 1:
Input:
grid = [[1,0,0,0],[1,1,1,0]]
hits = [[1,0]]
Output: [2]
Explanation:
If we erase the brick at (1, 0), the brick at (1, 1) and (1, 2) will drop. So we should return 2.
Example 2:
Input:
grid = [[1,0,0,0],[1,1,0,0]]
hits = [[1,1],[1,0]]
Output: [0,0]
Explanation:
When we erase the brick at (1, 0), the brick at (1, 1) has already disappeared due to the last move. So each erasure will cause no bricks dropping. Note that the erased brick (1, 0) will not be counted as a dropped brick.
Note:
我们有一组包含1和0的网格;其中1表示砖块。 当且仅当一块砖直接连接到网格的顶部,或者它至少有一块相邻(4 个方向之一)砖块不会掉落时,它才不会落下。我们会依次消除一些砖块。每当我们消除 (i, j) 位置时, 对应位置的砖块(若存在)会消失,然后其他的砖块可能因为这个消除而落下。返回一个数组表示每次消除操作对应落下的砖块数目。
注意:
count,然后每次打掉一个砖块以后,重建并查集,计算与天花板连通的砖块的个数 newCount,newCount - count -1 就是最终答案(打掉的那块砖块不计算其中),提交代码以后,发现 TLE。newCount - count -1 方式计算最终答案。注意每次还原一个砖块的时候需要染色回原有砖块的颜色 1 。优化成这样的做法,基本不会 TLE 了,如果计算 count 是单独计算的,还是会 TLE。如果没有进行秩压缩,时间会超过 1500 ms,所以这一题想拿到 100%,每步优化都要做好。最终 100% 的答案见代码。
package leetcode
import (
"github.com/halfrost/leetcode-go/template"
)
func hitBricks(grid [][]int, hits [][]int) []int {
if len(hits) == 0 {
return []int{}
}
uf, m, n, res, oriCount := template.UnionFindCount{}, len(grid), len(grid[0]), make([]int, len(hits)), 0
uf.Init(m*n + 1)
// 先将要打掉的砖块染色
for _, hit := range hits {
if grid[hit[0]][hit[1]] == 1 {
grid[hit[0]][hit[1]] = 2
}
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if grid[i][j] == 1 {
getUnionFindFromGrid(grid, i, j, uf)
}
}
}
oriCount = uf.Count()[uf.Find(m*n)]
for i := len(hits) - 1; i >= 0; i-- {
if grid[hits[i][0]][hits[i][1]] == 2 {
grid[hits[i][0]][hits[i][1]] = 1
getUnionFindFromGrid(grid, hits[i][0], hits[i][1], uf)
}
nowCount := uf.Count()[uf.Find(m*n)]
if nowCount-oriCount > 0 {
res[i] = nowCount - oriCount - 1
} else {
res[i] = 0
}
oriCount = nowCount
}
return res
}
func isInGrid(grid [][]int, x, y int) bool {
return x >= 0 && x < len(grid) && y >= 0 && y < len(grid[0])
}
func getUnionFindFromGrid(grid [][]int, x, y int, uf template.UnionFindCount) {
m, n := len(grid), len(grid[0])
if x == 0 {
uf.Union(m*n, x*n+y)
}
for i := 0; i < 4; i++ {
nx := x + dir[i][0]
ny := y + dir[i][1]
if isInGrid(grid, nx, ny) && grid[nx][ny] == 1 {
uf.Union(nx*n+ny, x*n+y)
}
}
}