2021.12.07LeetCode每日一题——边界着色

目录

边界着色

描述

示例 1

示例 2

示例 3

提示

方法一:堆栈(迭代)

方法二:深度优先搜索(递归)


边界着色

描述

给你一个大小为 m x n 的整数矩阵 grid ,表示一个网格。另给你三个整数 row、col 和 color 。网格中的每个值表示该位置处的网格块的颜色。

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

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

请你使用指定颜色 color 为所有包含网格块 grid[row][col] 的 连通分量的边界 进行着色,并返回最终的网格 grid 。

示例 1

输入:grid = [[1,1],[1,2]], row = 0, col = 0, color = 3
输出:[[3,3],[3,2]]

示例 2

输入:grid = [[1,2,2],[2,3,2]], row = 0, col = 1, color = 3
输出:[[1,3,3],[2,3,3]]

示例 3

输入:grid = [[1,1,1],[1,1,1],[1,1,1]], row = 1, col = 1, color = 2
输出:[[2,2,2],[2,1,2],[2,2,2]]

提示

  • m == grid.length
  • n == grid[i].length
  • 1 \le m, n \le 50
  • 1 \le grid[i][j], color \le 1000
  • 0 \le row < m
  • 0 \le col < n

这题目确实比较抽象不太好理解,大概意思可以简单认为有一个矩阵,如下图所示,假设我们给定的初始点为(2,2),即第三行第三列的位置,里面存储的是2,我们要找所有颜色为2的并与该点连通的区域即橙色区域,深橙色即为连通区域的边界,我们将这些边界赋值为传入的color,返回矩阵即可。

 

方法一:堆栈(迭代)

class Solution {
    public int[][] colorBorder(int[][] grid, int row, int col, int color) {
        Stack<int[]> stack = new Stack<>();//存放所有要访问的点
        boolean[][] isVisted = new boolean[grid.length][grid[0].length];//记录当前点是否被访问过
        int target = grid[row][col];//原连通分量中的值
        int[][] res=new int[grid.length][grid[0].length];
        for (int i = 0; i < grid.length; i++) for (int j = 0; j < grid[0].length; j++) res[i][j]=grid[i][j];//进行赋值
        stack.push(new int[]{row, col});
        while (!stack.isEmpty()) {
            int[] pop = stack.pop();//取出当前位置
            int curRow = pop[0], curCol = pop[1];

            //统计出上下左右四个方向的连通分量,加入到stack中
            if (curRow + 1 < grid.length && grid[curRow + 1][curCol] == target && !isVisted[curRow + 1][curCol])
                stack.push(new int[]{curRow + 1, curCol});
            if (curRow - 1 >= 0 && grid[curRow - 1][curCol] == target && !isVisted[curRow - 1][curCol])
                stack.push(new int[]{curRow - 1, curCol});
            if (curCol + 1 < grid[0].length && grid[curRow][curCol + 1] == target && !isVisted[curRow][curCol + 1])
                stack.push(new int[]{curRow, curCol + 1});
            if (curCol - 1 >= 0 && grid[curRow][curCol - 1] == target && !isVisted[curRow][curCol - 1])
                stack.push(new int[]{curRow, curCol - 1});

            //对当前连通分量进行判断是否赋值
            isVisted[curRow][curCol] = true;
            if (curRow == 0 || curRow == grid.length - 1 || curCol == 0 || curCol == grid[0].length - 1 ||
                    !(grid[curRow - 1][curCol] == target && grid[curRow + 1][curCol] == target &&
                            grid[curRow][curCol + 1] == target && grid[curRow][curCol - 1] == target)) {//如果是连通分量边界
                res[curRow][curCol] = color;//则将该块颜色赋值
            }
        }
        return res;
    }
}

方法二:深度优先搜索(递归)

class Solution {
    public int[][] colorBorder2(int[][] grid, int row, int col, int color) {
        int m = grid.length, n = grid[0].length;
        boolean[][] visited = new boolean[m][n];//记录当前点是否被访问过
        List<int[]> borders = new ArrayList<>();//存储边界点信息
        int originalColor = grid[row][col];//记录原始颜色
        visited[row][col] = true;
        dfs(grid, row, col, visited, borders, originalColor);//深搜
        for (int i = 0; i < borders.size(); i++) {
            int x = borders.get(i)[0], y = borders.get(i)[1];
            grid[x][y] = color;//对所有连通分量边界赋值
        }
        return grid;
    }

    public void dfs(int[][] grid, int x, int y, boolean[][] visited, List<int[]> borders, int originalColor) {
        int m = grid.length, n = grid[0].length;
        boolean isBorder = false;//标识当前点是否为连通分量边界
        int[][] direc = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
        for (int i = 0; i < 4; i++) {
            int nx = direc[i][0] + x, ny = direc[i][1] + y;
            if (!(nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == originalColor)) {
                isBorder = true;
            } else if (!visited[nx][ny]){
                visited[nx][ny] = true;
                dfs(grid, nx, ny, visited, borders, originalColor);
            }
        }
        if (isBorder) {//记录所有连通分量边界
            borders.add(new int[]{x, y});
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值