【leetcode 5040. 边框着色】解题报告

给出一个二维整数网格 grid,网格中的每个值表示该位置处的网格块的颜色。

只有当两个网格块的颜色相同,而且在四个方向中任意一个方向上相邻时,它们属于同一连通分量。

连通分量的边界是指连通分量中的所有与不在分量中的正方形相邻(四个方向上)的所有正方形,或者在网格的边界上(第一行/列或最后一行/列)的所有正方形。

给出位于 (r0, c0) 的网格块和颜色 color,使用指定颜色 color 为所给网格块的连通分量的边界进行着色,并返回最终的网格 grid 。

示例 1:

输入:grid = [[1,1],[1,2]], r0 = 0, c0 = 0, color = 3
输出:[[3, 3], [3, 2]]

示例 2:

输入:grid = [[1,2,2],[2,3,2]], r0 = 0, c0 = 1, color = 3
输出:[[1, 3, 3], [2, 3, 3]]

示例 3:

输入:grid = [[1,1,1],[1,1,1],[1,1,1]], r0 = 1, c0 = 1, color = 2
输出:[[2, 2, 2], [2, 1, 2], [2, 2, 2]]

提示:

  1. 1 <= grid.length <= 50
  2. 1 <= grid[0].length <= 50
  3. 1 <= grid[i][j] <= 1000
  4. 0 <= r0 < grid.length
  5. 0 <= c0 < grid[0].length
  6. 1 <= color <= 1000

方法一:dfs的非递归形式

扫描二维码关注公众号,回复: 6073786 查看本文章
  using ll=long long;
    const ll MAXN=50LL;
    unordered_set<ll> vis,mark;
    vector<vector<int>> colorBorder(vector<vector<int>>& G, int r0, int c0, int color) {
        queue<ll> Q;
        Q.push(r0*MAXN+c0);
        int c=G[r0][c0];
        int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
        while (!Q.empty())
        {
            int x=Q.front()/MAXN;
            int y=Q.front()%MAXN;
            Q.pop();
            vis.insert(x*MAXN+y);
            if (x==0||x==G.size()-1||y==0||y==G[0].size()-1)    // 边界方块可变色
                mark.insert(x*MAXN+y);
            else if (G[x-1][y]!=c||G[x+1][y]!=c||G[x][y-1]!=c||G[x][y+1]!=c)    // 四个方向中,任意一个方块颜色不同,则可变色
                mark.insert(x*MAXN+y);
            for (int d=0;d<4;d++)   // 放入连通分量的所有方块
            {
                int nx=x+dx[d],ny=y+dy[d];
                if (0<=nx&&nx<G.size()&&0<=ny&&ny<G[0].size()&&!vis.count(nx*MAXN+ny)&&G[nx][ny]==c)
                    Q.push(nx*MAXN+ny);
            }
        }
        for (auto it:mark)
            G[it/MAXN][it%MAXN]=color;
        return G;
    }

思路:用vis记录访问过的方块,mark标记连通分量中需要修改颜色的方块,并非连通分量中所有的方块都要修改颜色,比如:一个方块如果四周(四个方向邻接的)都是相同颜色,那么只需要修改四周方块的颜色,而自己颜色不变(开始的时候没理解题意,以为只要是连通分量内的方块颜色都需要改变)

方法二: dfs递归形式,只不过把上面的非递归改为递归了

    using ll=long long;
    const ll MAXN=50LL;
    unordered_set<ll> vis,mark;
    void dfs(vector<vector<int>>& G, int x, int y, int c)
    {
        int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
        vis.insert(x*MAXN+y);
        if (x==0||x==G.size()-1||y==0||y==G[0].size()-1)    // 边界方块可变色
            mark.insert(x*MAXN+y);
        else if (G[x-1][y]!=c||G[x+1][y]!=c||G[x][y-1]!=c||G[x][y+1]!=c)    // 四个方向中,任意一个方块颜色不同,则可变色
            mark.insert(x*MAXN+y);
        for (int d=0;d<4;d++)   // 放入连通分量的所有方块
        {
            int nx=x+dx[d],ny=y+dy[d];
            if (0<=nx&&nx<G.size()&&0<=ny&&ny<G[0].size()&&!vis.count(nx*MAXN+ny)&&G[nx][ny]==c)
                dfs(G,nx,ny,c);
        }
    }
    vector<vector<int>> colorBorder(vector<vector<int>>& G, int r0, int c0, int color) {
        dfs(G,r0,c0,G[r0][c0]);
        for (auto it:mark)
            G[it/MAXN][it%MAXN]=color;
        return G;
    }

方法三:dfs递归,但通过修改G中的数据,来记录是否访问过,和是否需要修改颜色,国外的一个大佬写的

From an initial point, perform DFS and flip the cell color to negative to track visited cells.

After DFS is complete for the cell, check if this cell is inside. If so, flip its color back to the positive.

In the end, cells with the negative color are on the border. Change their color to the target color.
image

void dfs(vector<vector<int>>& g, int r, int c, int cl) {
    if (r < 0 || c < 0 || r >= g.size() || c >= g[r].size() || g[r][c] != cl) return;    // 剪枝(越界,非着色块)
    g[r][c] = -cl;    // 着色
    dfs(g, r - 1, c, cl), dfs(g, r + 1, c, cl), dfs(g, r, c - 1, cl), dfs(g, r, c + 1, cl);
    if (r > 0 && r < g.size() - 1 && c > 0 && c < g[r].size() - 1 && cl == abs(g[r - 1][c]) &&
        cl == abs(g[r + 1][c]) && cl == abs(g[r][c - 1]) && cl == abs(g[r][c + 1]))    // 将原四周同色的块,颜色还原
        g[r][c] = cl;
}
vector<vector<int>> colorBorder(vector<vector<int>>& grid, int r0, int c0, int color) {
    dfs(grid, r0, c0, grid[r0][c0]);
    for (auto i = 0; i < grid.size(); ++i)    // 根据dfs标记(负数)过的方块进行着色
        for (auto j = 0; j < grid[i].size(); ++j) grid[i][j] = grid[i][j] < 0 ? color : grid[i][j];
    return grid;
}

猜你喜欢

转载自www.cnblogs.com/brianyi/p/10796990.html