Flood Fill 算法(漫水填充算法)是一种经典的图像处理技术,用于将连通区域内的所有像素替换为指定颜色。
核心思想:
从起始点开始,递归或迭代地将与其连通且颜色相同的所有像素替换为目标颜色,直到所有连通像素被处理完毕。
题目描述:
思路讲解:
本道题会给我们起始点和目标颜色 ,让我们将二维数组中起始点和与起始点连通并且与起始点颜色相同点的值修改为目标颜色 ,这里使用BFS解决,通过队列逐层处理所有与起始点原始颜色相同的连通像素(上下左右四个方向),并将其替换为目标颜色。以下是具体思路:
编写代码:
class Solution {
// 坐标上下左右需要加的数
int dx[4] = {0,0,-1,1};
int dy[4] = {1,-1,0,0};
public:
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc , int color)
{
if (image[sr][sc] == color)
return image;
int rows = image.size() , cols = image[0].size();
queue<pair<int, int>> qu;
int oldcolor = image[sr][sc];
qu.push({sr, sc});
while(!qu.empty())
{
int qu_x = qu.front().first, qu_y = qu.front().second;
image[qu_x][qu_y] = color;
qu.pop();
for(int i = 0 ; i < 4 ; i++)
{
int x = qu_x + dx[i] , y = qu_y + dy[i] ;
if(x >= 0 && x < rows && y >=0 && y < cols && image[x][y] == oldcolor)
qu.push({x,y});
}
}
return image;
}
};
思路讲解:
本道题给我们一个二维数组,想让我们找出岛屿的数量。
遍历二维数组中的每个位置,当遇到未访问的陆地(‘1’)时,通过 BFS 将其连通的所有陆地标记为 “已访问”(避免重复计数),并计数为一个岛屿,以下是具体思路:
实际上标记岛屿已被访问,可以将 ‘1’ 改为 ‘0’ ,但是我这里为了不修改原数组,就创建一个二维数组,对应原二维数组,标记该位置是否访问过。
编写代码:
class Solution {
int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};
public:
int numIslands(vector<vector<char>>& grid) {
// 与grid同规模的数组,false代表还没走过,true代表已经走过
vector<vector<bool>> vis(grid.size(),
vector<bool>(grid[0].size(), false));
queue<pair<int, int>> qu;
int ans = 0;
int rows = grid.size(), cols = grid[0].size();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == '1' && vis[i][j] == false) {
ans++;
vis[i][j] = true;
qu.push({i, j});
while (!qu.empty()) {
int qu_x = qu.front().first, qu_y = qu.front().second;
qu.pop();
for (int k = 0; k < 4; k++) {
int x = qu_x + dx[k], y = qu_y + dy[k];
if(x >= 0 && x < rows && y >= 0 && y < cols && grid[x][y] == '1' && vis[x][y] == false)
{
vis[x][y] = true;
qu.push({x,y});
}
}
}
}
}
}
return ans;
}
};
思路讲解:
本道题给我们一个二维数组,想让我们找出最大岛屿。
遍历二维数组中的每个点,当遇到未访问的陆地(‘1’)时,通过 BFS 将其连通的所有陆地标记为 “已访问”(避免重复计数),并在BFS的过程中记录岛屿的大小,通过对比得到最大岛屿的大小,以下是具体思路:
实际上标记岛屿已被访问,可以将 ‘1’ 改为 ‘0’ ,但是我这里为了不修改原数组,就创建一个二维数组,对应原二维数组,标记该点是否访问过。
编写代码:
class Solution {
int dx[4] = {0,0,-1,1};
int dy[4] = {1,-1,0,0};
public:
int maxAreaOfIsland(vector<vector<int>>& grid) {
vector<vector<bool>> vis(grid.size(),vector<bool> (grid[0].size(),false));
queue<pair<int,int>> qu;
int rows = grid.size() , cols = grid[0].size();
int ans = 0;
for(int i = 0 ; i < rows ; i++)
{
for(int j = 0 ; j < cols ; j++)
{
if(grid[i][j] == 1 && vis[i][j] == false)
{
qu.push({i,j});
vis[i][j] = true;
int tmp_max = 1;
while(!qu.empty())
{
int qu_x = qu.front().first , qu_y = qu.front().second;
qu.pop();
for(int k = 0 ; k < 4 ; k++)
{
int x = qu_x + dx[k] , y = qu_y + dy[k];
if(x >= 0 && x < rows && y >= 0 && y < cols && grid[x][y] == 1 && vis[x][y] == false)
{
vis[x][y] = true;
qu.push({x,y});
tmp_max++;
}
}
}
if(tmp_max > ans)
ans = tmp_max;
}
}
}
return ans;
}
};
思路讲解:
本道题给我们一个二维数组,想让我们将被 ‘X’ 包围的 'O’区域中的 ‘O’ 全部替换为 ‘X’,但是想直接找到被 ‘X’ 包围的 ‘O’ 并替换为 'X’需要两个步骤,首先是通过一次BFS判断该区域是否被包围,再通过一次BFS将被 ‘X’ 包围的 ‘O’ 替换为 ‘X’。
正向麻烦的话,就可以反向思考。先找出所有不被围绕的 ‘O’(即位于二维数组边缘或与边缘 ‘O’ 相连的 ‘O’),并将这些 ‘O’ 替换处 ‘O’ 和 ‘X’ 以外的字符;然后将剩余的 ‘O’(被围绕的区域)替换为 ‘X’。以下是具体思路:
编写代码:
class Solution {
int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};
int rows, cols;
public:
void bfs(vector<vector<char>>& board, vector<vector<bool>>& vis, int row , int col)
{
queue<pair<int, int>> qu;
qu.push({row, col});
board[row][col] = 'H';
while (!qu.empty())
{
int qu_x = qu.front().first, qu_y = qu.front().second;
qu.pop();
for (int k = 0; k < 4; k++) {
int x = qu_x + dx[k], y = qu_y + dy[k];
if (x >= 0 && x < rows && y >= 0 && y < cols &&
board[x][y] == 'O' && vis[x][y] == false)
{
board[x][y] = 'H';
qu.push({x, y});
}
}
}
}
void solve(vector<vector<char>>& board)
{
rows = board.size(), cols = board[0].size();
vector<vector<bool>> vis(rows, vector<bool>(cols, false));
for (int i = 0; i < cols; i++) {
if (board[0][i] == 'O' && vis[0][i] == false)
{
bfs(board, vis, 0 , i);
}
if (board[rows - 1][i] == 'O' && vis[rows - 1][i] == false)
{
bfs(board, vis, rows - 1, i);
}
}
for (int i = 0; i < rows; i++) {
if (board[i][0] == 'O' && vis[i][0] == false)
{
bfs(board, vis, i, 0);
}
if (board[i][cols - 1] == 'O' && vis[i][cols - 1] == false)
{
bfs(board, vis, i, cols - 1);
}
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (board[i][j] == 'O')
board[i][j] = 'X';
else if (board[i][j] == 'H')
board[i][j] = 'O';
}
}
}
};
如果有什么建议和疑问,或是有什么错误,大家可以在评论区中提出。
希望大家以后也能和我一起进步!!
如果这篇文章对你有用的话,希望大家给一个三连支持一下!!