BFS 解决 FloodFill 算法

题目一: 图像渲染

1. 题⽬链接:

https://leetcode.cn/problems/flood-fill/description/

2. 题⽬描述:

有⼀幅以 m x n 的⼆维整数数组表⽰的图画 image ,其中 image[i][j] 表⽰该图画的像素值⼤⼩。 你也被给予三个整数
sr , sc 和 newColor 。你应该从像素 image[sr][sc] 开始对图像进⾏ 上⾊填充 。 为了完成 上⾊⼯作
,从初始像素开始,记录初始坐标的 上下左右四个⽅向上 像素值与初始坐标相同 的相连像素点,接着再记录这四个⽅向上符合条件的像素点与他们对应
四个⽅向上 像素值与初始坐 标相同的相连像素点,……,重复该过程。将所有有记录的像素点的颜⾊值改为 newColor 。 最后返回
经过上⾊渲染后的图像 。

在这里插入图片描述
在这里插入图片描述

3. 算法思路:

可以利⽤「深搜」或者「宽搜」,遍历到与该点相连的所有「像素相同的点」,然后将其修改成指定的像素即可,本题这里采取的解法是利用队列+深搜哦。

4.代码

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, n = image[0].length;
 Queue<int[]> q = new LinkedList<>();
 q.add(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], y = b + dy[i];
 if(x >= 0 && x < m && y >= 0 && y < n && image[x][y] == prev)
 {
 q.add(new int[]{x, y});
 }
 }
 }
 return image;
 }
 }

题目二: 岛屿数量

1. 题⽬链接:

https://leetcode.cn/problems/number-of-islands/description/

2. 题⽬描述:

给你⼀个由 ‘1’(陆地)和 ‘0’(⽔)组成的的⼆维⽹格,请你计算⽹格中岛屿的数量。
岛屿总是被⽔包围,并且每座岛屿只能由⽔平⽅向和/或竖直⽅向上相邻的陆地连接形成。 此外,你可以假设该⽹格的四条边均被⽔包围。

在这里插入图片描述

3. 算法思路:

遍历整个矩阵,每次找到**「⼀块陆地」**的时候:

• 说明找到**「⼀个岛屿」**,记录到最终结果 ret ⾥⾯;


并且将这个陆地相连的所有陆地,也就是这块「岛屿」,全部「变成海洋」。这样的话,我们下次遍历到这块岛屿的时候,它「已经是海洋」了,不会影响最终结果。

• 其中「变成海洋」的操作,可以利⽤「深搜」和「宽搜」解决,其实就是上一题 图像渲染 这道题~ 这样,当我们,遍历完全部的矩阵的时候,
ret 存的就是最终结果。

4.代码

在这里class Solution 
{
 int[] dx = {0, 0, -1, 1};
 int[] dy = {1, -1, 0, 0};
 boolean[][] vis = new boolean[301][301];
 int m, n;
 public int numIslands(char[][] grid) 
 {
 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' && !vis[i][j])
 {
 ret++;
 bfs(grid, i, j);
 }
 }
 }
 return ret;
 }
 public void bfs(char[][] grid, int i, int j)
 {
 Queue<int[]> q = new LinkedList<>();
 q.add(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], y = b + dy[k];
 if(x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == '1' && 
!vis[x][y])
 {
 q.add(new int[]{x, y});
 vis[x][y] = true;
 }
 }

 }
 }
}



插入代码片

题目三:被围绕的区域

1. 题⽬链接:

https://leetcode.cn/problems/surrounded-regions/description/

2. 题⽬描述:

给你⼀个 m x n 的矩阵 board ,由若⼲字符 ‘X’ 和 ‘O’ ,找到所有被 ‘X’ 围绕的区域,并将这些区域 ⾥所有的 ‘O’
⽤ ‘X’ 填充。

在这里插入图片描述

提示:

m == board.length n == board[i].length 1 <= m, n <= 200 board[i][j] 为
‘X’ 或 ‘O’

3. 算法思路:

算法思路:
正难则反。 可以先利⽤ bfs 将与边缘相连的 ‘0’ 区域做上标记,然后重新遍历矩阵,将没有标记过的 ‘0’

修改成 ‘X’ 即可。

4.代码

class Solution 
{
 int[] dx = {0, 0, 1, -1};
 int[] dy = {1, -1, 0, 0};
 int m, n;
 public void solve(char[][] board) 
 {
 m = board.length; n = board[0].length;
 // 1. 先处理边界的 'O' 联通块,全部修改成 '.' 
 for(int j = 0; j < n; j++)
 {
 if(board[0][j] == 'O') bfs(board, 0, j);
 if(board[m - 1][j] == 'O') bfs(board, m - 1, j);
 }
 for(int i = 0; i < m; i++)
 {
 if(board[i][0] == 'O') bfs(board, i, 0);
 if(board[i][n - 1] == 'O') bfs(board, i, n - 1);
 }
 // 2. 还原 
 for(int i = 0; i < m; i++)
 for(int j = 0; j < n; j++)
 if(board[i][j] == 'O') board[i][j] = 'X';
 else if(board[i][j] == '.') board[i][j] = 'O';
 }
 public void bfs(char[][] board, int i, int j)
 {
 Queue<int[]> q = new LinkedList<>();
 q.add(new int[]{i, j});
 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], y = b + dy[k];
 if(x >= 0 && x < m && y >= 0 && y < n && board[x][y] == 'O')
 {
 board[x][y] = '.';
 q.add(new int[]{x, y});
 }
 }
 }
 }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值