803. 打砖块

Posted STWILLD

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了803. 打砖块相关的知识,希望对你有一定的参考价值。

难度 hard
有一个 m x n 的二元网格,其中 1 表示砖块,0 表示空白。砖块 稳定(不会掉落)的前提是:

一块砖直接连接到网格的顶部,或者
至少有一块相邻(4 个方向之一)砖块 稳定 不会掉落时
给你一个数组 hits ,这是需要依次消除砖块的位置。每当消除 hits[i] = (rowi, coli) 位置上的砖块时,对应位置的砖块(若存在)会消失,然后其他的砖块可能因为这一消除操作而掉落。一旦砖块掉落,它会立即从网格中消失(即,它不会落在其他稳定的砖块上)。

返回一个数组 result ,其中 result[i] 表示第 i 次消除操作对应掉落的砖块数目。

注意,消除可能指向是没有砖块的空白位置,如果发生这种情况,则没有砖块掉落。

示例 1:

输入:grid = [[1,0,0,0],[1,1,1,0]], hits = [[1,0]]
输出:[2]
解释:
网格开始为:
[[1,0,0,0],
[1,1,1,0]]
消除 (1,0) 处加粗的砖块,得到网格:
[[1,0,0,0]
[0,1,1,0]]
两个加粗的砖不再稳定,因为它们不再与顶部相连,也不再与另一个稳定的砖相邻,因此它们将掉落。得到网格:
[[1,0,0,0],
[0,0,0,0]]
因此,结果为 [2] 。
示例 2:

输入:grid = [[1,0,0,0],[1,1,0,0]], hits = [[1,1],[1,0]]
输出:[0,0]
解释:
网格开始为:
[[1,0,0,0],
[1,1,0,0]]
消除 (1,1) 处加粗的砖块,得到网格:
[[1,0,0,0],
[1,0,0,0]]
剩下的砖都很稳定,所以不会掉落。网格保持不变:
[[1,0,0,0],
[1,0,0,0]]
接下来消除 (1,0) 处加粗的砖块,得到网格:
[[1,0,0,0],
[0,0,0,0]]
剩下的砖块仍然是稳定的,所以不会有砖块掉落。
因此,结果为 [0,0] 。

提示:

m == grid.length
n == grid[i].length
1 <= m, n <= 200
grid[i][j] 为 0 或 1
1 <= hits.length <= 4 * 104
hits[i].length == 2
0 <= xi <= m - 1
0 <= yi <= n - 1
所有 (xi, yi) 互不相同

解题思路:这道题目是看了grandyang的解法后,才解决的,思路就是,用一个HashSet来保存稳定的砖块,以grid[i][j]为例,保存对应的索引i*n+j,(n是列数),然后用set的size来更新结果。我们直接的思路就是,从第一行的砖块深度遍历来计算砖块的数量,然后去掉某个砖块后,再次从第一行的砖块深度遍历来计算砖块数量,这样两次遍历完后,砖块数量的差值就是去掉一块转后掉落的砖块,但这种搜索方法就不是很高效。我们可以尝试这种方法,首先把所有需要去掉的砖块都去掉,这样先遍历一遍,得到最后剩下的砖块数量,然后从最后一块砖头开始往回加,每加一块砖头,我们就用深度遍历把和他相连的砖头加入hashset中,增加的砖头就是原来消除这块砖头之后会掉的砖头。具体地,我们先把hits对应的需要消除的位置减一,然后统计依次最后剩下砖头的数量,然后从hits的最后一个位置开始往回加,如果加完不是一,说明原来的位置是0,直接跳过,如果是一,那就看周边有没有稳定的砖块存在(也就是在set中)或者是否是第0行,如果是的话,那就对当前元素进行深度遍历,结束后用set的前后size的差异减去一,就是掉落的砖头数,减一是因为去掉的砖头不算在掉落的砖头中。

代码 t31 s23 java

class Solution {
    public int[] hitBricks(int[][] grid, int[][] hits) {
        HashSet<Integer> set = new HashSet<>();
        int m = grid.length, n = grid[0].length;
        int len = hits.length;
        int[] res = new int[len];
        for(int i=0; i<len; i++){
            grid[hits[i][0]][hits[i][1]] -= 1;
        }
        for(int i=0; i<grid[0].length; i++){
            helper(grid, 0, i, set);
        }
        for(int i=len-1; i>=0; i--){
            int oldSize = set.size(), x = hits[i][0], y = hits[i][1];
            if(++grid[x][y]!=1) continue;
            else{
                if((x+1<m && set.contains((x+1)*n+y)) ||
                (x-1>=0 && set.contains((x-1)*n+y)) ||
                (y+1<n && set.contains(x*n+y+1)) ||
                (y-1>=0 && set.contains(x*n+y-1)) ||
                x==0){
                    helper(grid, x, y, set);
                    res[i] = set.size() - oldSize - 1;
                } 
            }
        }
        return res;
    }

    public void helper(int[][]grid, int i, int j, HashSet<Integer> set){
        int m = grid.length, n = grid[0].length;
        int t = i * n + j;
        if(i<0 || i>=m || j<0 || j>=n || grid[i][j]!=1 || set.contains(t))  return;
        set.add(t);
        helper(grid, i+1, j, set);
        helper(grid, i, j+1, set);
        helper(grid, i-1, j, set);
        helper(grid, i, j-1, set);
    }
}

参考资料:
https://www.cnblogs.com/grandyang/p/9362777.html

以上是关于803. 打砖块的主要内容,如果未能解决你的问题,请参考以下文章

打砖块代码

一百多行js代码实现打砖块小游戏

P1174 打砖块

C语言项目实战:《打砖块》零基础项目丨225 行源码注释示例

P1174 打砖块

Codevs 1257 打砖块