自学内容网 自学内容网

【BFS】解决FloodFill 算法

图像渲染

模版:

算法思路:

  1. 起始点:从给定的起始点开始,检查该点的颜色是否与目标颜色相同(如果相同,才会继续填充)。
  2. 队列:使用队列来存储待填充的像素。对于每个从队列中取出的像素,我们将其相邻的四个方向(上、下、左、右)的像素加入队列,继续填充。
  3. 边界检查:每次检查相邻像素时,要保证不会超出边界。
  4. 终止条件:当队列为空时,填充完成。
import java.util.LinkedList;
import java.util.Queue;

class Solution {
    // 四个方向:上、下、左、右
    int[] dx = {0, 0, 1, -1};
    int[] dy = {1, -1, 0, 0};

    public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
        int oldColor = image[sr][sc]; // 获取起始点的颜色
        if (oldColor == newColor) {
            return image; // 如果起始点的颜色和目标颜色相同,直接返回
        }

        int m = image.length; // 图像的行数
        int n = image[0].length; // 图像的列数

        // BFS的队列
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[]{sr, sc}); // 将起始点加入队列
        image[sr][sc] = newColor; // 将起始点的颜色更新为新颜色

        // BFS 填充过程
        while (!queue.isEmpty()) {
            int[] curr = queue.poll();
            int x = curr[0], y = curr[1];

            // 遍历四个方向
            for (int i = 0; i < 4; i++) {
                int nx = x + dx[i], ny = y + dy[i];

                // 检查新位置是否在图像范围内,并且与原始颜色相同
                if (nx >= 0 && nx < m && ny >= 0 && ny < n && image[nx][ny] == oldColor) {
                    image[nx][ny] = newColor; // 将该位置的颜色更新为新颜色
                    queue.offer(new int[]{nx, ny}); // 将该位置加入队列
                }
            }
        }

        return image;
    }
}

class Solution {
    //设置偏移量 上下左右四个坐标
    int[] dx = { 0, 0, 1, -1 };
    int[] dy = { 1, -1, 0, 0 };

    public int[][] floodFill(int[][] image, int sr, int sc, int color) {
        // 记录初始颜色
        int prev = image[sr][sc];

        // 初始颜色和目标颜色相同,则直接返回原图
        if (prev == color)
            return image;

        int m = image.length;
        int n = image[0].length;
        // 构造一个队列,先把起始点放进去
        Queue<int[]> q = new LinkedList<>();
        q.offer(new int[] { sr, sc });
        // 当队列不为空 
        while (!q.isEmpty()) {
            int[] t = q.poll();
            int a = t[0], b = t[1];
            // 改变颜色
            image[a][b] = color;
            // 遍历四个方向
            for (int i = 0; i < 4; i++) {
                int x = a + dx[i];
                int y = b + dy[i];
                // 防止越界 并且上下左右如果有跟原来的颜色相同 加入队列并修改颜色
                if (x >= 0 && x < m && y >= 0 && y < n && image[x][y] == prev) {
                    q.offer(new int[] { x, y });
                }
            }
        }
        return image;
    }
}

岛屿数量

 

解题思路

  1. 遍历每个网格: 从左到右、从上到下依次遍历整个二维网格。如果当前位置是陆地('1'),并且没有访问过(vis[i][j] 是 false),则说明发现了一个新的岛屿,岛屿计数加1。
  2. 使用 BFS标记岛屿: 当发现一个新的岛屿后,利用广度优先搜索(BFS)从当前 '1' 开始,遍历整个岛屿并标记所有岛屿上的 '1' 为已访问(vis[i][j] 设置为 true),这样可以避免重复计算。
  3. BFS 过程:
    • 将当前的陆地节点加入队列。
    • 从队列中取出一个节点,检查它的四个方向(上下左右)。
    • 如果相邻的位置是陆地并且未被访问过,就将这个位置加入队列,并标记为已访问。
    • 重复此过程,直到队列为空,即完成了一个岛屿的所有陆地的遍历。

class Solution {
    // 设置偏移量
    int[] dx = { 0, 0, 1, -1 };
    int[] dy = { 1, -1, 0, 0 };
    // 用来标记是否记录过当前岛屿
    boolean[][] vis;
    int m, n;

    public int numIslands(char[][] grid) {
        m = grid.length;
        n = grid[0].length;
        vis = new boolean[m][n];

        int ret = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == '1' && vis[i][j] == false) {
                    ret++;
                    // 并且将此岛屿都标记成使用过
                    bfs(grid, i, j);
                }
            }
        }
        return ret;
    }

    void bfs(char[][] grid, int i, int j) {
        Queue<int[]> q = new LinkedList<>();
        q.offer(new int[] { i, j });
        vis[i][j] = true;

        while (!q.isEmpty()) {
            int[] t = q.poll();
            int a = t[0], b = t[1];
            for (int k = 0; k < 4; k++) {
                int x = a + dx[k];
                int y = b + dy[k];
                if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == '1' && vis[x][y] == false) {
                    q.offer(new int[] { x, y });
                    vis[x][y] = true;
                }
            }
        }
    }
}

 岛屿的最大面积

跟上题相似,找到一块区域,只需统计这块区域的个数即可

class Solution {
    // 设置偏移量
    int[] dx = { 0, 0, 1, -1 };
    int[] dy = { 1, -1, 0, 0 };

    // 记录岛屿的面积
    boolean[][] vis;
    int m, n;

    public int maxAreaOfIsland(int[][] grid) {
        m = grid.length;
        n = grid[0].length;
        vis = new boolean[m][n];
        int max = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                // 找到一块岛屿
                if (grid[i][j] == 1 && vis[i][j] == false) {
                    // 计算面积
                    max = Math.max(max, bfs(grid, i, j));
                }
            }
        }
        return max;
    }

    int bfs(int[][] grid, int i, int j) {
        int count = 1;
        Queue<int[]> q = new LinkedList<>();
        q.offer(new int[] { i, j });
        while (!q.isEmpty()) {

            int[] t = q.poll();
            int a = t[0], b = t[1];
            vis[a][b] = true;
            for (int k = 0; k < 4; k++) {
                int x = a + dx[k], y = b + dy[k];
                if (x >= 0 && x < m && y >= 0 && y < n
                        && grid[x][y] == 1 && vis[x][y] == false) {
                    q.offer(new int[] { x, y });
                    vis[x][y] = true;
                    count++;
                }
            }
        }

        return count;
    }
}

 被围绕的区域

1.只需先把四周边界位置的'O'先找到 利用bfs 替换成其他符号 例如‘?’

2.遍历整个范围  不是 ‘?’的全部变成 ‘X’ 是‘?’的变成 ‘O’

class Solution {
    int[] dx = { 0, 0, 1, -1 };
    int[] dy = { 1, -1, 0, 0 };

    int m, n;
    boolean[][] vis;

    public void solve(char[][] board) {
        m = board.length;
        n = board[0].length;
        vis = new boolean[m][n];

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (i == 0 || i == m - 1 || j == 0 || j == n - 1) {
                    if (board[i][j] == 'O' && !vis[i][j]) {
                        // 都标记为其他字符 ?
                        bfs(board, i, j);
                    }
                }
            }
        }

        // 遍历
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if(board[i][j] != '?') {
                    board[i][j] = 'X';
                } else {
                    board[i][j] = 'O';
                }
            }
        }
    }

    void bfs(char[][] board, int i, int j) {
        Queue<int[]> q = new LinkedList<>();
        q.offer(new int[] { i, j });
        vis[i][j] = true;
        board[i][j] = '?';

        while (!q.isEmpty()) {
            int[] t = q.poll();
            int a = t[0], b = t[1];
            for (int k = 0; k < 4; k++) {
                int x = a + dx[k];
                int y = b + dy[k];
                if (x >= 0 && x < m && y >= 0 && y < n
                        && board[x][y] == 'O' && !vis[x][y]) {
                    q.offer(new int[] { x, y });
                    board[x][y] = '?';
                    vis[x][y] = true;
                }
            }
        }
    }
}


原文地址:https://blog.csdn.net/chaodddddd/article/details/145140748

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!