803. 打磚塊
我們有一組包含1和0的網格;其中1表示磚塊。 當且僅當一塊磚直接連接到網格的頂部,或者它至少有一塊相鄰(4 個方向之一)磚塊不會掉落時,它纔不會落下。
我們會依次消除一些磚塊。每當我們消除 (i, j) 位置時, 對應位置的磚塊(若存在)會消失,然後其他的磚塊可能因爲這個消除而落下。
返回一個數組表示每次消除操作對應落下的磚塊數目。
示例 1:
輸入:
grid = [[1,0,0,0],[1,1,1,0]]
hits = [[1,0]]
輸出: [2]
解釋:
如果我們消除(1, 0)位置的磚塊, 在(1, 1) 和(1, 2) 的磚塊會落下。所以我們應該返回2。
示例 2:
輸入:
grid = [[1,0,0,0],[1,1,0,0]]
hits = [[1,1],[1,0]]
輸出:[0,0]
解釋:
當我們消除(1, 0)的磚塊時,(1, 1)的磚塊已經由於上一步消除而消失了。所以每次消除操作不會造成磚塊落下。注意(1, 0)磚塊不會記作落下的磚塊。
注意:
網格的行數和列數的範圍是[1, 200]。
消除的數字不會超過網格的區域。
可以保證每次的消除都不相同,並且位於網格的內部。
一個消除的位置可能沒有磚塊,如果這樣的話,就不會有磚塊落下。
class Solution {
int count=0;
public int[] hitBricks(int[][] grid, int[][] hits) {
int[] ret = new int[hits.length];
// 先把磚塊打掉
for(int[] hit : hits){
if(grid[hit[0]][hit[1]] == 1)
grid[hit[0]][hit[1]] = -1;
}
// 貼上最頂層的磚塊和與最頂層連接的磚塊
for(int k = 0; k < grid[0].length; ++k){
if(grid[0][k] == 1){
isWayToTop(grid, 0, k);
}
}
for(int i = hits.length - 1; i >= 0; --i){
count = 0;
//在刪掉之前的情況下,如果能保存的話,就恢復此磚塊,因爲後面可能有和這個磚塊有聯繫的
//可能導致前面的磚塊先over,導致後面的掉了,我們可以把他做恢復模擬
if(canHit(grid, hits[i][0], hits[i][1]) && grid[hits[i][0]][hits[i][1]] == -1){
isWayToTop(grid, hits[i][0], hits[i][1]);
ret[i] = count - 1;
}
}
return ret;
}
public void isWayToTop(int[][] grid, int i, int j){
grid[i][j] = 2;
++ count;
if (i + 1 < grid.length && grid[i + 1][j] == 1) {
isWayToTop(grid, i + 1, j);
}
if (j + 1 < grid[0].length && grid[i][j + 1] == 1) {
isWayToTop(grid, i, j + 1);
}
if (i-1>=0&& grid[i - 1][j] == 1) {
isWayToTop(grid, i - 1, j);
}
if (j - 1 >= 0 && grid[i][j - 1] == 1) {
isWayToTop(grid, i, j - 1);
}
}
public boolean canHit(int [][] grid,int i,int j){
if(i == 0)
return true;
if (i + 1 < grid.length && grid[i + 1][j] == 2) {
return true;
}
if (j + 1 < grid[0].length && grid[i][j + 1] == 2) {
return true;
}
if (i - 1 >= 0 && grid[i - 1][j] == 2) {
return true;
}
if (j - 1 >= 0 && grid[i][j - 1] == 2) {
return true;
}
if(grid[i][j] == -1)
grid[i][j] = 1;
return false;
}
}