网格图刷题(一)—— DFS 深度优先搜索

             适用于判断连通块个数、大小相关的题目;

求连通岛屿的数量及面积

1. 岛屿数量

200. 岛屿数量

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

输入:grid = [
  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
输出:1
class Solution {
    public int numIslands(char[][] grid) {
        // DFS 
        // 每次向下,水平进行搜索;搜到了就把所有的变为2(访问之后的);
        // 遇到一个1就开始搜索一次
        // 每搜索一次,岛屿数量加1
        int count = 0;
        for(int i=0; i< grid.length; i++) {
            for(int j=0; j<grid[i].length; j++) {
                if(grid[i][j] == '1') { // 当前元素为1,则生成岛屿
                    dfs(grid,i,j);
                    count ++;
                }
            }
        }
        return count;
    }

// dfs 生成当成元素的岛屿
// 访问当前的 grid,x, y 为当前访问的坐标
    void dfs(char[][] grid,int x,int y) {
        if(x<0 || x >= grid.length || y < 0 || y >= grid[0].length) {
            return ; // 超界直接return
        }
        if(grid[x][y] == '0' || grid[x][y] == '2'){ // 如果搜索到0或2了,也不继续下搜索了
            return ;
        }
        if(grid[x][y] == '1') { // 等于1就把这个修改为2,然后继续往四周搜索
            grid[x][y] = '2';
        }
        dfs(grid,x-1,y); // 往上走
        dfs(grid,x,y+1);
        dfs(grid,x,y-1);
        dfs(grid,x+1,y);
        return ;
    }
}

2. 岛屿的最大面积

695. 岛屿的最大面积

给你一个大小为 m x n 的二进制矩阵 grid 。

        岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

岛屿的面积是岛上值为 1 的单元格的数目。

计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。

// 注: 也可以不维护全局变量,而是把dfs函数的返回值设置为int,通过dfs函数来传递每个岛屿的面积
class Solution {
    int max = 0;
    int size = 0; // 记录当前的面积
    public int maxAreaOfIsland(int[][] grid) {
        // dfs 出每个岛屿,并记录岛屿的面积
        for(int i=0; i<grid.length ; i++) {
            for(int j=0; j < grid[0].length; j++) {
                if(grid[i][j] == 1) {
                    size = 0; // 更新size
                    dfs(grid,i,j);
                    max = Math.max(max,size);
                }
            }
        }
        return max;
    }

    //1. x  , y 为当前遍历到的元素
    void dfs(int[][]grid, int x, int y) {
        // 2. 处理这个元素
        // 2.1 元素越界 return 
        if(x < 0 || x >= grid.length || y < 0 || y >= grid[0].length) {
            return ;
        }
        // 2.2 元素已经被处理完,或者元素为0;return
        if(grid[x][y] != 1) {
            return ;
        }
        // 2.3 标记元素,并继续向下搜索
        grid[x][y] = 2;
        size ++;
        dfs(grid,x,y+1);
        dfs(grid,x,y-1);
        dfs(grid,x-1,y);
        dfs(grid,x+1,y);
    }
}

3. 水域大小

面试题 16.19. 水域大小

总结:主要能学到的是如何对八个方向进行遍历;以及在dfs中设置返回值。通过设置返回值来计算得到每一个水域的大小;

class Solution {
    int[][] land;
    int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0},{1,1},{1,-1},{-1,-1},{-1,1}}; // 八个方向
    public int[] pondSizes(int[][] land) {
        // 水域大小问题:值为0表示的是水域,然后如果值为0则表示水域;
        // 思路:
        //     1. 从网格图0出发,然后dfs访问八个方向的0;把这些0进行标记
        //     2. dfs过程中记录池塘的大小;
        //     3. dfs完之后放入数组中,再对数组进行排序即可
        // 总结:与前面的题目相比就是在dfs的过程中从之前遍历四个方向,现在变成了遍历八个方向
        this.land = land;
        int m = land.length, n = land[0].length;
        var ans = new ArrayList<Integer>();
        for(int i=0; i<m ; i++) {
            for(int j=0; j < n; j++) {
                if(land[i][j] == 0) {
                    ans.add(dfs(i,j));
                }
            }
        }
        // 把list转换成int数组
        var size = new int[ans.size()];
        int i=0;
        for(int x : ans) 
            size[i++] = x; 
        Arrays.sort(size);
        return size;
    }
    // 返回值为当前岛屿的大小
    public int dfs(int x, int y) { // 传入当前访问的元素下标
        // 1. 越界则返回,或当前元素被访问过
        if(x < 0 || x >= land.length || y<0 || y >= land
        [0].length||land[x][y] != 0) {
            return 0;
        }
        land[x][y] = 1; // 记录访问过了
        int count = 1; // 记录元素数目,表示当前有岛屿数1
        // 3. 访问8个方向; 
        for(var dir : dirs) {
            count += dfs(x+dir[0], y+dir[1]); // dfs(i,j)从这个点得到的岛屿数,那以一个中心点,然后加上它8个方向可构成的岛屿数,不就得到了最后的岛屿数        
        }
        return count;
    }
}

- 4. 主题空间

LCS 03. 主题空间

「以扣会友」线下活动所在场地由若干主题空间与走廊组成,场地的地图记作由一维字符串型数组 grid,字符串中仅包含 "0"~"5" 这 6 个字符。地图上每一个字符代表面积为 1 的区域,其中 "0" 表示走廊,其他字符表示主题空间。相同且连续(连续指上、下、左、右四个方向连接)的字符组成同一个主题空间。

假如整个 grid 区域的外侧均为走廊。请问,不与走廊直接相邻的主题空间的最大面积是多少?如果不存在这样的空间请返回 0

        Notice: 在元素被访问后一般会设置一个标记,表示该位置已经被访问过;要注意在判断dfs结束条件时要加上如果访问到的是已经被遍历过的元素,那么就直接返回;

class Solution {
    int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0}};
    boolean flag = true; // 标记是否与走廊相邻
    char[][] gridCh;
    char cur; // 记录开始访问的元素值
    public int largestArea(String[] grid) {
        // DFS: 同样是深搜;
        // 如果搜到旁边不是相同的数字,则结束搜索,长度++;但是如果搜索到0了;或者搜索出界了,那这个空间就不考虑了
        // 所以两个部分 1. 在旁边数字不相同时搜索停止;
                    // 2. 此时判断搜索停止时的数字,若为0或者则直接结束;搜出界也结束
        // 先转化成一个二维数组方便操作
        // 并记录空间的大小,如何设置空间的总大小为0呢
        // 如何结束不也是个问题? 可以设置一个flag ; 如果为false表示这个空间不进行考虑了;
        //                      然后每次遍历一个主题空间时重新更新这个flag值。
        // 四个方向进行搜索

        // 1. 把这个string数组转成一个二维char数组
        char[][] gridCh = new char[grid.length][grid[0].length()]; 
        char[] chs;
        for(int i=0; i<grid.length; i++) {
            chs = grid[i].toCharArray();
            gridCh[i] = chs; 
        }
        this.gridCh = gridCh;
        // for(int i=0; i<gridCh.length; i++) {
        //     for(int j=0; j<gridCh[0].length; j++) {
        //         System.out.print(gridCh[i][j]+" ");
        //     }
        //     System.out.println();
        // }
        // 2. 遍历这个二维char类型数组
        int ans = 0; // 记录最大的空间面积
        for(int i=0; i<gridCh.length; i++) {
            for(int j=0; j<gridCh[0].length; j++) {
                // if(gridCh[i][j] == '6') {
                //     continue;
                // }
                cur = gridCh[i][j];
                int count = dfs(i,j); // 得到当前的一个区域面积
                if(flag) { // 表明当前的考虑
                    ans = Math.max(count,ans);
                }
                flag = true; // 更新flag
            }
        }
        return ans;
    }
    public int dfs(int x,int y) {
        if(x < 0 || x >= gridCh.length || y<0 || y>=gridCh[0].length || gridCh[x][y] == '0') {
            flag = false; // 超界 或着 遇到的元素是1 表明该主题空间与走廊相邻了
            return 0;
        }
        // 没有超界,但是遇到的元素与当前的元素不同,则返回0
        // 或者该元素已经被访问过
        if(gridCh[x][y] != cur || gridCh[x][y] == '6') {
            return 0;
        } 
        // 这里修改为6之后,再次访问时间就会出现问题
        gridCh[x][y] = '6'; // 把当前的元素标记为6表示访问过
        int count = 1; //表明当前空间大小为1
        for(var dir : dirs) {
            count += dfs(x+dir[0],y+dir[1]);
        }
        return count;
    }
}

5. 岛屿的周长

463. 岛屿的周长

给定一个 row x col 的二维网格地图 grid ,其中:grid[i][j] = 1 表示陆地, grid[i][j] = 0 表示水域。

网格中的格子 水平和垂直 方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。

岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。

class Solution {
    int[][] grid;
    int m,n;
    int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0}};
    public int islandPerimeter(int[][] grid) {
        // 使用dfs深搜完成
        // 每一个岛屿都会往四个方向进行搜素,如果搜素到的是水域或者是出界了,那么边数就+1;
        // 最后结果即为这个岛屿的周长; 
        // 只有一个岛屿
        this.grid = grid;
        int m = grid.length;
        int n = grid[0].length;
        this.m = m; this.n = n;
        int ans = 0;
        for(int i=0; i<m; i++) {
            for(int j=0; j<n; j++) {
                if(grid[i][j] == 1) {
                    ans = dfs(i,j);
                }
            }
        }
        return ans;
    }

    // c => circumference 周长
    public int dfs(int x, int y) {
        if(x < 0 || x >=m || y<0 || y>= n || grid[x][y] == 0) {
            // 出界 或 遇到水域了
            return 1;
        } 
        if(grid[x][y] == 2) {
            return 0;
        }
        // 到这里表明遇到是普通的岛屿,标记已经访问
        int c = 0;
        grid[x][y] = 2; //表明被访问过   
        for(var dir : dirs) {
            c += dfs(x + dir[0], y+dir[1]);   // 这个dfs返回的是当前这个岛屿返回的当前周长了吧
        }
        return c;
    }
}

其他不使用dfs或bfs的解决思路

代码随想录 (programmercarl.com)icon-default.png?t=O83Ahttps://www.programmercarl.com/kamacoder/0106.%E5%B2%9B%E5%B1%BF%E7%9A%84%E5%91%A8%E9%95%BF.html#%E6%80%9D%E8%B7%AF

6. 网格图中鱼的最大数目

2658. 网格图中鱼的最大数目

本题可以转化为求岛屿的最大面积,没有区别的

class Solution {
    // 记录四个方位,与把grid放到全局变量,代码会更加优雅
    private final static int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    private int[][] grid;  
    public int findMaxFish(int[][] grid) {
        // 执行任意次操作,就是可以在一个水域群中任意移动
        // 相当于是在求所有水域中面积最大的那个
        this.grid = grid;
        int ans = 0; 
        for(int i=0; i<grid.length; i++) {
            for(int j=0; j < grid[0].length; j++) {
                ans = Math.max(ans, dfs(i,j));
            }
        }
        return ans;
    }

    // dfs 表示从r,c出发可捕获的最大鱼数
    public int dfs(int r, int c) {
        if(r < 0 || r >= grid.length || c < 0 || c >= grid[0].length) {
            return 0; 
        }
        if(grid[r][c] == 0 ) { // 不能再继续移动了
            return 0;
        }
        int sum = grid[r][c]; // 记录当前水域的值
        grid[r][c] = 0; // 更新
        for(var dir : dirs) {
            sum += dfs(r+dir[0], c+dir[1]);
        }
        return sum;
    }
}

如何判断当前元素是边缘元素

7. 边界着色

1034. 边界着色

// 连通分量:即一个岛屿
class Solution {
    int m;
    int n;
    int [][] grid;
    int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0}};
    boolean[][] visited;
    int color; 
    int originColor; // 记录最初的元素
    public int[][] colorBorder(int[][] grid, int row, int col, int color) {
        // step1: 确定连通分量
        // step2: 将连通分量中在边框上的,或者四个方向上存在不是自己相同元素的进行标记,并且进行染色
        this.grid = grid;
        this.m = grid.length;
        this.n = grid[0].length;
        boolean[][] visited = new boolean[m][n];
        for(int i=0; i<m; i++) {
            for(int j=0; j<n; j++) {
                visited[i][j] = false;
            }
        }
        this.visited = visited;
        this.color = color;
        this.originColor= grid[row][col];
        dfs(row,col);
        return grid;
    }

    
    // 标记满足上述两个条件的块; 想使用一个visited数组来完成
    public void dfs(int x, int y) {
        visited[x][y] = true;
        for(var dir : dirs) {
            int x1 = x + dir[0]; int y1 = y + dir[1]; // 下一个元素
            if(x1 < 0 || x1 >= m || y1 < 0 || y1 >= n) {
                // 出界
                grid[x][y] = color;
            }else { // 没有出界
                if(visited[x1][y1]) {  
                    continue;
                }
                if(grid[x1][y1] == originColor){ // 颜色相同,一定要与最初的颜色进行对比,否则颜色可能会被修改
                    dfs(x1,y1);
                }else {
                    grid[x][y] = color; // 颜色不同
                }
            }
        }
    }
}

寻找孤岛的思路

反向思路:孤岛即在湖中间的岛屿,这些岛屿不与边界的水域相连;我们要找到它可以从边界出发,进行dfs或bfs,把边界可达的岛屿都变成水域(淹城法),经过这样的操作之后,再遍历整个grid数组,其中剩下的岛屿元素就都是属于孤岛了。

8. 飞地的数量

1020. 飞地的数量

给你一个大小为 m x n 的二进制矩阵 grid ,其中 0 表示一个海洋单元格、1 表示一个陆地单元格。

一次 移动 是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过 grid 的边界。

返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。

class Solution {
    int[][] grid;
    int m,n;
    int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1}};
    public int numEnclaves(int[][] grid) {
        // 从边缘进行 “淹城”
        this.grid = grid;
        this.m = grid.length;
        this.n = grid[0].length;
        for(int i=0; i < m; i++) {
            if(grid[i][0] == 1) { // 第一列元素
                dfs(i,0);
            }
            if(grid[i][n-1] == 1) { // 最后一列元素
                dfs(i,n-1);
            }
        }
        for(int j=0; j<n; j++) { 
            if(grid[0][j] == 1) { // 第一行元素
                dfs(0,j);
            }
            if(grid[m-1][j] == 1) { // 最后一行元素
                dfs(m-1,j);
            }
        }

        int ans = 0;
        for(int i=0; i<m; i++) {
            for(int j=0; j<n; j++) {
                if(grid[i][j] == 1) {
                    ans ++;
                }
            }
        }
        return ans;
    }

    
    // 将grid[x][y] 可达的都变成水域
    public void dfs(int x, int y) {
        if(x < 0 || x>=m || y < 0 || y>=n || grid[x][y] == 0) return;
        grid[x][y] = 0;
        for(var dir : dirs) {
            dfs(x+dir[0],y+dir[1]); 
        }
    }
}

9. 矩阵中移动的最大次数

2684. 矩阵中移动的最大次数

给你一个下标从 0 开始、大小为 m x n 的矩阵 grid ,矩阵由若干  整数组成。

你可以从矩阵第一列中的 任一 单元格出发,按以下方式遍历 grid :

  • 从单元格 (row, col) 可以移动到 (row - 1, col + 1)(row, col + 1) 和 (row + 1, col + 1) 三个单元格中任一满足值 严格 大于当前单元格的单元格。

返回你在矩阵中能够 移动 的 最大 次数。

10.  统计封闭岛屿的数目

1254. 统计封闭岛屿的数目

二维矩阵 grid 由 0 (土地)和 1 (水)组成。岛是由最大的4个方向连通的 0 组成的群,封闭岛是一个 完全 由1包围(左、上、右、下)的岛。

请返回 封闭岛屿 的数目。

class Solution {
    int[][] grid;
    int m;
    int n;
    int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0}};
    public int closedIsland(int[][] grid) {
        /**
            返回封闭岛屿的数目
            逆向思维:可以从四边出发,即把四边的土地可以延申到的地方全部变成水域
                    此时剩下的就只有孤岛了
                然后统计孤岛的数目即可;相当于是在统计岛屿数目
         */
        this.grid = grid;
        this.m = grid.length;
        this.n = grid[0].length;
        for(int i=0; i < m; i++) {
            if(grid[i][0] == 0) dfs(i,0);
            if(grid[i][n-1] == 0) dfs(i,n-1);
        }
        for(int j=0; j<n; j++) {
            if(grid[0][j] == 0) dfs(0,j);
            if(grid[m-1][j] == 0) dfs(m-1,j);
        }
        // 到这一步的时候此时grid只剩孤岛元素了;
        int count = 0; //统计孤岛数目
        for(int i=0; i< m; i++) {
            for(int j =0 ; j<n; j++) {
                if(grid[i][j] == 0){
                    dfs(i,j);
                    count ++;
                }
            }
        }
        return count;
    }

    // 将四周的土地变成1
    public void dfs(int x, int y) {
        if(x < 0 || x>= m || y< 0 || y>=n || grid[x][y] == 1) {
            return ;
        }
        grid[x][y] = 1;
        for(var dir : dirs) {
            dfs(x + dir[0], y + dir[1]);
        }
    }
}

11. 被围绕的区域

        结合 visited 数组来从边界访问

130. 被围绕的区域

给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' 组成,捕获 所有 被围绕的区域

  • 连接:一个单元格与水平或垂直方向上相邻的单元格连接。
  • 区域:连接所有 'O' 的单元格来形成一个区域。
  • 围绕:如果您可以用 'X' 单元格 连接这个区域,并且区域中没有任何单元格位于 board 边缘,则该区域被 'X' 单元格围绕。

通过将输入矩阵 board 中的所有 'O' 替换为 'X' 来 捕获被围绕的区域

class Solution {
    char[][] board;
    int m;
    int n;
    int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0}};
    boolean[][] visited;
    public void solve(char[][] board) {
        /** 
            被包围的区域就是无法到达边界的区域
            反向思考:也就是从边界无法到达的区域
                可以从边界的O出发,标记与其连接的O;最后遍历一遍grid,将未访问到的 O 全部变成X 即可
        */
        // 初始化
        this.board = board;
        this.m = board.length;
        this.n = board[0].length;
        boolean[][] visited = new boolean[m][n];
        for(int i=0; i<m; i++) {
            for(int j=0; j<n; j++) {
                visited[i][j] = false;
            }
        }
        this.visited = visited;

        for(int i=0; i < m; i++) {
            if(board[i][0] == 'O') { // 第一列元素
                dfs(i,0);
                visited[i][0] = true;
            }
            if(board[i][n-1] == 'O') { // 最后一列元素
                dfs(i,n-1);
                visited[i][n-1] = true;
            }
        }
        for(int j=0; j<n; j++) { 
            if(board[0][j] == 'O') { // 第一行元素
                dfs(0,j);
                visited[0][j] = true;
            }
            if(board[m-1][j] == 'O') { // 最后一行元素
                dfs(m-1,j);
                visited[m-1][j] = true;
            }
        }

        for(int i=0; i< m; i++) {
            for(int j=0; j<n; j++) {
                if(board[i][j] == 'O' && !visited[i][j]) {
                    board[i][j] = 'X';
                }
            }
        }
    }
    
    public void dfs(int x,int y) {
        if(x < 0 || x>=m || y < 0 || y >= n || visited[x][y] || board[x][y] == 'X') {
            return ;
        }
        visited[x][y] = true;
        for(var dir : dirs) {
            dfs(x+dir[0], y + dir[1]);
        }
    }
}

两个岛屿图下找到子岛屿 —— 叠图法

12. 统计子岛屿

1905. 统计子岛屿

给你两个 m x n 的二进制矩阵 grid1 和 grid2 ,它们只包含 0 (表示水域)和 1 (表示陆地)。一个 岛屿 是由 四个方向 (水平或者竖直)上相邻的 1 组成的区域。任何矩阵以外的区域都视为水域。

如果 grid2 的一个岛屿,被 grid1 的一个岛屿 完全 包含,也就是说 grid2 中该岛屿的每一个格子都被 grid1 中同一个岛屿完全包含,那么我们称 grid2 中的这个岛屿为 子岛屿 。

请你返回 grid2 中 子岛屿 的 数目 。

示例 1:

输入:grid1 = [[1,1,1,0,0],[0,1,1,1,1],[0,0,0,0,0],[1,0,0,0,0],[1,1,0,1,1]], grid2 = [[1,1,1,0,0],[0,0,1,1,1],[0,1,0,0,0],[1,0,1,1,0],[0,1,0,1,0]]
输出:3
解释:如上图所示,左边为 grid1 ,右边为 grid2 。
grid2 中标红的 1 区域是子岛屿,总共有 3 个子岛屿。
class Solution {
    int m;
    int n;
    int[][] grid;
    boolean isSubLand = true;
    int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1}};
    public int countSubIslands(int[][] grid1, int[][] grid2) {
        /**
            子岛屿:即grid1的岛屿中的一部分是grid2岛屿
            返回grid2 中子岛屿的数目

            叠图法:将grid2与grid1进行重叠即数值相加;
                    注意不可以直接相加,否则岛屿都会出现部分为1,部分为2的情况;
                    而是当grid2 与 grid1的相同位置同时为2时才可以相加
                    此时如果为grid1的子岛屿,那么此时grid2中该岛屿的元素应全部都是2;
                    如果部分为2,另一部分为1,则说明这不是子岛屿
                    而且这个1只可能是grid2自己留下来的
            最后只用统计grid2中全为2的岛屿数目即可。
         */
        this.m = grid1.length;
        this.n = grid1[0].length;
        // 1. 叠图:将两个grid数组相加
        for(int i=0; i < m; i++) {
            for(int j =0; j<n; j++) {
                if(grid2[i][j] == grid1[i][j])
                grid2[i][j] += grid1[i][j];
                System.out.print(grid2[i][j] + " ");
            }
            System.out.println();
        }
        this.grid = grid2;
        
        // 2. 求grid2中只含2的岛屿数目
        // 碰到1了就说明当前统计的这个岛屿是一个部分子岛屿,不能被统计,设置一个flag标示
        int count = 0;
         for(int i=0; i < m; i++) {
            for(int j =0; j<n; j++) {
                if(grid[i][j] == 2) { // 当前元素是2
                    dfs(i,j);
                    if(isSubLand) {
                        count ++;
                    }
                    isSubLand = true; // 更新 标识
                }
            }
        }
        return count;
    }

    
    public void dfs(int x, int y) {
        if(x < 0 || x>=m || y < 0 || y>=n || grid[x][y] == 0) return;
        if(grid[x][y] == 1) { // 碰到1了
            isSubLand = false;
            return ;
        }
        grid[x][y] = 0 ;// 标示已经访问过的
        for(var dir : dirs) {
            dfs(x + dir[0], y + dir[1]);
        }
    }
}
// 下面的算法更快
// 思路与上面相同,不过是只有grid2为1时就相加,这样不会出现grid2中本来是0,却把grid1中的1加过来的情况
// class Solution {
//     boolean find;
//     public int countSubIslands(int[][] grid1, int[][] grid2) {
//         int n = grid1.length,m = grid1[0].length;
//         for(int i = 0; i < n; i++){
//             for(int j = 0; j< m; j++){
//                 if(grid2[i][j] == 1) // 如果gird2中为1就相加
//                 grid2[i][j] += grid1[i][j];
//             }
//         }
//         int ans =0;
//         for(int i = 0; i < n;i++){
//             for(int j = 0;j  < m; j++){
//                 if(grid2[i][j] == 2){
//                     find = true;
//                     dfs(grid2,i,j);
//                     if(find) ans++;
//                 }
//             }
//         }
//         return ans;

//     }
//     void dfs(int[][] grid,int i,int j){
//         if(i < 0 || j < 0 || i == grid.length || j == grid[0].length) return;
//         if(grid[i][j] == 1){ // 遇到1了表示不是
//             find = false;
//             return;
//         }
//         if(grid[i][j] == 0) return;
//         grid[i][j] = 0;
//         dfs(grid,i-1,j);
//         dfs(grid,i,j+1);
//         dfs(grid,i+1,j);
//         dfs(grid,i,j-1);
//     }
// }

13.  检查网格中是否存在有效路径

1391. 检查网格中是否存在有效路径

给你一个 m x n 的网格 grid。网格里的每个单元都代表一条街道。grid[i][j] 的街道可以是:

  • 1 表示连接左单元格和右单元格的街道。
  • 2 表示连接上单元格和下单元格的街道。
  • 3 表示连接左单元格和下单元格的街道。
  • 4 表示连接右单元格和下单元格的街道。
  • 5 表示连接左单元格和上单元格的街道。
  • 6 表示连接右单元格和上单元格的街道。

你最开始从左上角的单元格 (0,0) 开始出发,网格中的「有效路径」是指从左上方的单元格 (0,0) 开始、一直到右下方的 (m-1,n-1) 结束的路径。该路径必须只沿着街道走

注意:你 不能 变更街道。

如果网格中存在有效的路径,则返回 true,否则返回 false 。

示例 1:

输入:grid = [[2,4,3],[6,5,2]]
输出:true
解释:如图所示,你可以从 (0, 0) 开始,访问网格中的所有单元格并到达 (m - 1, n - 1) 。

注:文章中的很多算法思路以及代码参考自灵茶山艾府及代码随想录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值