首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >LeetCode 803. 打砖块(并查集)

LeetCode 803. 打砖块(并查集)

作者头像
Michael阿明
发布2021-02-19 14:54:10
发布2021-02-19 14:54:10
4600
举报

文章目录

1. 题目

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

  • 一块砖直接连接到网格的顶部,或者
  • 至少有一块相邻(4 个方向之一)砖块 稳定 不会掉落时

给你一个数组 hits ,这是需要依次消除砖块的位置。 每当消除 hits[i] = (rowi, coli) 位置上的砖块时,对应位置的砖块(若存在)会消失,然后其他的砖块可能因为这一消除操作而掉落。 一旦砖块掉落,它会立即从网格中消失(即,它不会落在其他稳定的砖块上)。

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

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

代码语言:javascript
复制
示例 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 * 10^4
hits[i].length == 2
0 <= xi <= m - 1
0 <= yi <= n - 1
所有 (xi, yi) 互不相同

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/bricks-falling-when-hit 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

并查集学习

  • 先复制一份地图,把要敲的地方先敲掉
  • 使用并查集合并剩余的砖块
  • 逆序遍历敲击的砖块,合并周围砖块,记录 top 砖块所在集团在合并前后的 size 之差
代码语言:javascript
复制
class dsu // 并查集
{
    int top;
    vector<int> f;
public:
    vector<int> count;//某节点对应集团的总节点个数
    dsu(int n)
    {
        f.resize(n);
        count.resize(n);
        for(int i = 0 ;i < n; ++i)
            f[i] = i, count[i] = 1;
    }
    int find(int a)
    {
        if(a == f[a])
            return a;
        return f[a] = find(f[a]);
    }
    void merge(int a, int b)
    {
        int fa = find(a), fb = find(b);
        if(fa != fb)
        {
            f[fa] = fb;
            count[fb] += count[fa];
        }
    }
};
class Solution {
public:
    vector<int> hitBricks(vector<vector<int>>& grid, vector<vector<int>>& hits) {
        int m = grid.size(), n = grid[0].size(), len = hits.size();
        vector<int> ans(len, 0);
        vector<vector<int>> copy(grid);
        for(auto& h : hits)
            copy[h[0]][h[1]] = 0;//先敲掉
        dsu u(m*n+1);
        int top = m*n;
        vector<vector<int>> dir = {{-1,0},{0,-1},{1,0},{0,1}};
        for(int j = 0; j < n; ++j)
            if(copy[0][j]==1)
                u.merge(j, top);
        for(int i = 1; i < m; ++i)
        {
            for(int j = 0; j < n; ++j)
            {
                if(copy[i][j]==1)
                {
                    for(int k = 0; k < 4; ++k)
                    {
                        int x = i + dir[k][0];
                        int y = j + dir[k][1];
                        if(x>=0 && x < m && y>=0 && y<n && copy[x][y]==1)
                        {
                            u.merge(x*n+y, i*n+j);
                        }
                    }
                }
            }
        }
        for(int i = len-1; i >= 0; --i)
        {
            int x0 = hits[i][0], y0 = hits[i][1];
            if(grid[x0][y0]==0)
                continue;//原来就是空的,敲了不起作用
            int ct1 = u.count[u.find(top)];// 注意要先find top 的 father
            for(int k = 0; k < 4; ++k)
            {
                int x = x0 + dir[k][0];
                int y = y0 + dir[k][1];
                if(x>=0 && x < m && y>=0 && y<n && copy[x][y]==1)
                {
                    u.merge(x*n+y, x0*n+y0);
                }
            }
            if(x0 == 0)
                u.merge(y0, top);
            ans[i] = max(0, u.count[u.find(top)]-ct1-1);
            copy[x0][y0]=1;//填回去
        }
        return ans;
    }
};

384 ms 107.2 MB C++


本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/01/16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 1. 题目
  • 2. 解题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档