一.题目

二.思路讲解
2.1 思路讲解
本题除了用 DFS 实现,同样可以采用 BFS(广度优先搜索) 来完成图像渲染。
-
从起点
(sr, sc)开始,将其颜色改为color,并记录原始颜色。 -
使用一个队列,将起点入队。
-
当队列不为空时,取出队头元素,检查它的 四个方向(上、下、左、右)的邻居格子。
-
若邻居格子 在边界内 、颜色等于原始颜色 、尚未被访问 ,则将其颜色改为
color,并加入队列。 -
重复此过程,直到队列为空。
三.代码演示
cpp
class Solution
{
public:
int bx[4] = {0,0,-1,1};
int by[4] = {1,-1,0,0};
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color)
{
int prev = image[sr][sc];//获取一开始要渲染的值
//如果渲染的值和新渲染值相同那么直接返回
if(prev == color) return image;
int row = image.size();//行
int col = image[0].size();//列
queue<pair<int,int>> q;//队列存储的是坐标
q.push({sr,sc});
while(q.size())
{
auto& [a,b] = q.front();//[a,b]直接获取q存储的坐标,auto会自动符合类型
q.pop();
image[a][b] = color;//给它渲染
for(int k = 0;k < 4;k++)
{
int x = a + bx[k],y = b + by[k];
if(x >= 0 && y >= 0 && x < row && y < col && image[x][y] == prev)
{
q.push({x,y});
}
}
}
return image;
}
};
四.代码讲解
一、方向数组与变量定义
-
bx[4]、by[4]:表示上、下、左、右四个方向的偏移量。{0,0,-1,1}分别对应右、左、上、下(顺序不重要,只要四个方向覆盖即可)。
-
prev:记录起点像素的原始颜色,用于判断相邻格子是否属于同一连通区域。 -
row、col:分别记录图像的行数和列数,用于边界检查。 -
q:队列,存储待处理的像素坐标(x, y),用于实现广度优先搜索。
二、主函数 floodFill
-
获取原始颜色 :
int prev = image[sr][sc]; -
提前返回 :如果
prev == color,说明新颜色与原始颜色相同,无需任何操作,直接返回原图。 -
获取图像尺寸 :
row = image.size(); col = image[0].size(); -
初始化队列 :将起点
(sr, sc)入队。 -
BFS 循环:当队列不为空时,重复以下步骤:
-
取出队头坐标
(a, b),弹出队列。 -
将当前像素颜色改为
color。 -
遍历四个方向,计算新坐标
(x, y)。 -
若新坐标在边界内且其颜色等于原始颜色
prev,则将其入队(等待后续处理)。
-
-
返回结果:所有连通区域处理完毕后,返回修改后的图像。
三、BFS 过程细节
-
队列的 FIFO 特性:保证了按层扩散,但本题不关心顺序,只需全部遍历即可。
-
入队时机 :在检查到邻居格子颜色等于
prev时立即入队,避免重复检查。 -
颜色修改时机 :在从队列取出节点时修改,也可以入队前修改,但当前代码在取出时修改是安全的,因为入队前没有修改,可能会重复入队同一格子?实际上,由于入队前并未修改颜色,同一个格子可能被多次加入队列(因为多个邻居可能都指向它)。但这里在入队前没有检查该格子是否已被处理,所以会导致重复入队,造成大量冗余操作。 注意 :当前代码存在重复入队 的问题:一个格子可能被多个方向同时发现并加入队列,但由于未标记已处理,它会被多次入队。虽然最终结果正确,但效率会降低。更优的做法是在入队前先修改颜色或使用
visited数组标记,避免重复入队。
四、关键细节
-
提前返回优化:若新颜色与原始颜色相同,直接返回原图,避免不必要的遍历。
-
边界检查 :每次生成邻居坐标后,必须检查其是否在
[0, row)和[0, col)范围内。 -
颜色比较 :判断邻居颜色是否等于
prev,而不是等于color,因为尚未修改的格子颜色才是原始颜色。 -
队列元素类型 :使用
pair<int,int>存储坐标,C++ 中可以用{x, y}构造,auto& [a,b]结构绑定简化代码。
五、流程图
