BFS 解决 FloodFill 算法
- 题目一: 图像渲染
- 1. 题⽬链接:
- 2. 题⽬描述:
- 3. 算法思路:
- 4.代码
- 题目二: 岛屿数量
- 1. 题⽬链接:
- 2. 题⽬描述:
- 3. 算法思路:
- 4.代码
- 题目三:被围绕的区域
- 1. 题⽬链接:
- 2. 题⽬描述:
- 3. 算法思路:
- 4.代码
题目一: 图像渲染
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});
}
}
}
}
}