LeetCode-803. BrickBreaker

descripción

Hay una cuadrícula binaria mxn, donde 1 significa ladrillo y 0 significa espacio en blanco. La premisa de que los ladrillos son estables (no caerán) son:

Cuando un ladrillo está conectado directamente a la parte superior de la cuadrícula, o
al menos un ladrillo adyacente (una de las 4 direcciones) es estable y no se caerá,
se le dará una serie de golpes, que es donde deben estar los ladrillos. eliminado a su vez. Siempre que se elimine el ladrillo en la posición de hits [i] = (rowi, coli), el ladrillo en la posición correspondiente (si lo hay) desaparecerá, y luego otros ladrillos pueden caer debido a esta operación de eliminación. Una vez que un ladrillo cae, desaparecerá inmediatamente de la cuadrícula (es decir, no caerá sobre otros ladrillos estables).

Devuelve un resultado de matriz, donde resultado [i] representa el número de ladrillos caídos correspondiente a la i-ésima operación de eliminación.

Tenga en cuenta que la eliminación puede apuntar a una posición en blanco sin ladrillos. Si esto sucede, no caerán ladrillos.

 

Ejemplo 1:

Entrada: cuadrícula = [[1,0,0,0], [1,1,1,0]], hits = [[1,0]]
Salida: [2]
Explicación: La
cuadrícula comienza como:
[[1 , 0,0,0],
 [1,1,1,0]]
elimine los ladrillos engrosados en (1,0) para obtener la cuadrícula:
[[1,0,0,0]
 [0,1, 1, 0]] Los
dos ladrillos en negrita ya no son estables porque ya no están conectados a la parte superior y ya no están adyacentes a otro ladrillo estable, por lo que caerán. Obtener la cuadrícula:
[[1,0,0,0],
 [0,0,0,0]]
Por lo tanto, el resultado es [2].
Ejemplo 2:

Entrada: cuadrícula = [[1,0,0,0], [1,1,0,0]], hits = [[1,1], [1,0]]
Salida: [0,0]
Explicación:
La cuadrícula comienza como:
[[1,0,0,0],
 [1,1,0,0]]
Elimine los ladrillos engrosados en (1,1) para obtener la cuadrícula:
[[1,0,0, 0 ],
 [1,0,0,0]] Los
ladrillos restantes son muy estables, por lo que no se caerán. La cuadrícula permanece sin cambios:
[[1,0,0,0], 
 [1,0,0,0]]
Luego, elimine los ladrillos engrosados ​​en (1,0) para obtener la cuadrícula:
[[1, 0,0 , 0],
 [0,0,0,0]] Los
ladrillos restantes aún son estables, por lo que no caerán ladrillos.
Por tanto, el resultado es [0,0].
 

rápido:

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

Fuente:
Enlace de LeetCode : https://leetcode-cn.com/problems/bricks-falling-when-hit/

 

Solución (consulte la respuesta oficial de leetcode: https://leetcode-cn.com/problems/bricks-falling-when-hit/solution/da-zhuan-kuai-by-leetcode-solution-szrq/ )

    // 使用散列表实现一个动态增加的并查集
    class VarUnionFind {
    private:
        unordered_map<int, int> parent;
        unordered_map<int, int> rank;
        unordered_map<int, int> sz;
    public:
        int find(int p) {
            if (parent.count(p) == 0) {
                // 如果p在散列表中不存在,则添加进去
                parent[p] = p; // 初始指向自己
                rank[p] = 1; // 初始层级为1
                sz[p] = 1; // 初始数量为1
                return p;
            }
            while (p != parent[p]) {
                parent[p] = parent[parent[p]]; // 路径压缩,优化查找速度
                p = parent[p];
            }
            return p;
        }

        void unionElements(int p, int q) {
            int pRoot = find(p);
            int qRoot = find(q);
            if (pRoot == qRoot) {
                return;
            }
            if (rank[pRoot] < rank[qRoot]) {
                parent[pRoot] = qRoot;
                sz[qRoot] += sz[pRoot];
                return;
            }
            if (rank[pRoot] > rank[qRoot]) {
                parent[qRoot] = pRoot;
                sz[pRoot] += sz[qRoot];
                return;
            }
            // rank[pRoot] == rank[qRoot]
            parent[pRoot] = qRoot;
            sz[qRoot] += sz[pRoot];
            ++rank[qRoot];
        }

        // 获取当前连通分量内的元素数量
        int getCount(int p) {
            return sz[find(p)];
        }
    };


    class Solution {
    public:
        vector<int> hitBricks(vector<vector<int>> &grid, vector<vector<int>> &hits) {
            const int h = grid.size();
            const int w = grid[0].size();
            auto status = grid;
            // 将需要粉碎的砖块位置均重置为0,便于逆序处理
            for (auto &vec : hits) {
                status[vec[0]][vec[1]] = 0;
            }

            // 并查集关联
            VarUnionFind uf;
            for (int r = 0; r < h; ++r) {
                for (int c = 0; c < w; ++c) {
                    if (status[r][c] == 1) {
                        if (r == 0) {
                            uf.unionElements(h * w, c); // h * w用来表示第一行的特殊点
                        }
                        if (r > 0 && status[r - 1][c] == 1) {
                            uf.unionElements(r * w + c, (r - 1) * w + c);
                        }
                        if (c > 0 && status[r][c - 1] == 1) {
                            uf.unionElements(r * w + c, r * w + c - 1);
                        }
                    }
                }
            }

            // 计算结果
            vector<std::pair<int, int>> directions{
   
   {1,  0},{0,  1},{-1, 0},{0,  -1}};
            const int n = hits.size();
            vector<int> res(n, 0);
            for (int i = n - 1; i >= 0; --i) {
                int r = hits[i][0];
                int c = hits[i][1];
                if (grid[r][c] == 0) {
                    continue;
                }
                int prevCount = uf.getCount(h * w); // 获取当前节点添加前的连通量节点数量
                if (r == 0) {
                    uf.unionElements(c, h * w); // h * w用来表示第一行的特殊点
                }

                for (auto &[x, y] : directions) {
                    int nr = r + x;
                    int nc = c + y;
                    if (nr >= 0 && nr < h && nc >= 0 && nc < w) {
                        // 与当前节点的上下左右1节点关联
                        if (status[nr][nc] == 1) {
                            uf.unionElements(nr * w + nc, r * w + c);
                        }
                    }
                }
                int curCount = uf.getCount(h * w);
                res[i] = std::max(0, curCount - prevCount - 1);
                status[r][c] = 1;
            }
            return res;
        }
    };

 

Supongo que te gusta

Origin blog.csdn.net/u010323563/article/details/112718142
Recomendado
Clasificación