【Java数据结构与算法】二维网格搜索逻辑判断细节及[岛屿数量]、[边界着色]题解

逻辑判断上下左右的新点

  int[][] direct = {{0,1},{0,-1},{1,0},{-1,0}};
  while(xxx){
  int x=当前点x, y= 当前点y
  //一个for循环得到四个新点,可以将其当作一种情况进行判断
  for (int i = 0; i < 4; i++) {
     int nx = direct[i][0] + x, ny = direct[i][1] + y;
     逻辑判断新点
     if(nx... &&  ny...) {
     
     }
  }

力扣200.岛屿数量

思路:遍历二维数组,碰到1就把所有和1连起来的改成其他数

class Solution {
    public int numIslands(char[][] grid) {
        int m = grid.length, n = grid[0].length;
        int ret = 0;
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(grid[i][j] == '1') {
                    ret++;
                    //所有的相连的1全改成2;这样下次就找不到它了
                    bfs(grid,i,j);
                    //或者
                    //dfs(grid,i,j);
                }
            }
        }
        return ret;
    }
    void bfs(char[][] grid, int x, int y) {...}
    void dfs(char[][] grid, int x, int y) {...}
}

深度优先搜索(DFS):

    int[][] direct = {{1,0},{-1,0}, {0,1}, {0,-1}};
    //一直往是1的方向走,走过的地方改成1,走到头没路了就回溯到上一个分叉口换条路走
    void dfs(char[][] grid, int x, int y) {
        int m = grid.length, n = grid[0].length;
        grid[x][y] = 0;
        for(int i = 0; i < 4; i++) {
            int nx = direct[i][0] + x, ny = direct[i][1] + y;
            if(nx >=0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == '1') {
               dfs(grid,nx,ny);
            }
        }
    }

由于这道题判断上下左右的x y进入递归的情况较为简单,可以不引入for循环和方向,简化如下

    void dfs2(char[][] grid, int x, int y) {
        int m = grid.length;
        int n = grid[0].length;
        if (x < 0 || y < 0 || x >= m || y >= n || grid[x][y] == '0') {
            return;
        }
        grid[x][y] = '0';
        dfs2(grid, x - 1, y);
        dfs2(grid, x + 1, y);
        dfs2(grid, x, y - 1);
        dfs2(grid, x, y + 1);
    }

广度优先搜索(BFS):


    int[][] direct = {{1,0},{-1,0}, {0,1}, {0,-1}};
    //广度优先搜索,把1周围是1的改为0
    void bfs(char[][] grid, int x, int y) {
        int m = grid.length, n = grid[0].length;
        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[]{x,y});
        grid[x][y] = 0;
        while(queue.size() > 0) {
            int[] cur = queue.poll();
            int curx = cur[0], cury = cur[1];
            for(int i = 0; i < 4; i++) {
                int nx = direct[i][0] + curx, ny = direct[i][1] + cury;
                if(nx >=0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == '1') {
                    queue.add(new int[]{nx, ny});
                    grid[nx][ny] = 0;
                }
            }
        }
    }

力扣1034.边界着色

深度优先搜索(DFS):
用递归进行深度优先搜索,一直往一个方向搜索,只要新点是在连通区域,内且

class Solution {
    int[][] direct = {{1,0}, {-1,0}, {0,1}, {0,-1}};
    List<int[]> bound = new ArrayList<>();
    public int[][] colorBorder(int[][] grid, int row, int col, int color) {
          int m = grid.length, n = grid[0].length;
          boolean[][] vis = new boolean[m][n];
          dfs(grid,vis,row, col, grid[row][col]);
          for(int i = 0; i < bound.size(); i++) {
              grid[bound.get(i)[0]][bound.get(i)[1]] = color;
          }
        return grid;
    }

    void dfs(int[][] grid, boolean[][] vis, int x, int y, int orginColor) {
        int m = grid.length, n = grid[0].length;
        vis[x][y] =true;
        boolean isBound = false;
        for(int i = 0; i < 4; i++) {
            int nx = direct[i][0] + x, ny = direct[i][1] + y;
            if(!(nx >=0 && nx < m && ny >=0 && ny < n && grid[nx][ny] == orginColor)){
                isBound = true;
            }else if(!vis[nx][ny]) {
                dfs(grid,vis,nx, ny, orginColor);
            }
        }
        if(isBound){
            bound.add(new int[]{x,y});
        }
    }
}

广度优先搜索(BFS):
用队列保存要遍历的结点,进行广度优先搜索,搜索过的做标记,新点在连通区内且未被访问过这加入队列,回头继续从这个点搜索。记录是边界的点,最后将grid中边界的点改掉。

class Solution {
    public int[][] colorBorder(int[][] grid, int row, int col, int color) {
        int m = grid.length, n = grid[0].length;
        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[]{row, col});
        boolean[][] vis = new boolean[m][n];
        List<int[]> bound = new ArrayList<>();
        int[][] direct = {{0,1},{0,-1},{1,0},{-1,0}};
        int oriColor = grid[row][col];
        while (queue.size() > 0) {
            int[] poll = queue.poll();
            int x = poll[0], y = poll[1];
            boolean isBound =false;
            for (int i = 0; i < 4; i++) {
                int nx = direct[i][0] + x, ny = direct[i][1] + y;
                //不满足任意一个,说明此点是边界
                if(!(nx >=0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == oriColor)){
                    isBound = true;
                }else if(!vis[nx][ny]) {
                    vis[nx][ny] = true;
                    queue.add(new int[]{nx,ny});
                }
            }
            if(isBound){
                bound.add(new int[]{x,y});
            }
        }
        for (int i = 0; i < bound.size(); i++) {
          grid[bound.get(i)[0]][bound.get(i)[1]] = color;
        }
        return grid;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甲 烷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值