一【题目类别】
- 广度优先搜索
二【题目难度】
- 简单
三【题目编号】
- 面试题 08.10. 颜色填充
四【题目描述】
- 编写函数,实现许多图片编辑软件都支持的「颜色填充」功能。
- 待填充的图像用二维数组
image
表示,元素为初始颜色值。初始坐标点的行坐标为sr
列坐标为sc
。需要填充的新颜色为newColor
。 - 「周围区域」是指颜色相同且在上、下、左、右四个方向上存在相连情况的若干元素。
- 请用新颜色填充初始坐标点的周围区域,并返回填充后的图像。
五【题目示例】
- 示例:
- 输入:
image = [[1,1,1],[1,1,0],[1,0,1]]
sr = 1, sc = 1, newColor = 2
- 输出:
[[2,2,2],[2,2,0],[2,0,1]]
- 解释:
- 初始坐标点位于图像的正中间,坐标
(sr,sc)=(1,1)
。 - 初始坐标点周围区域上所有符合条件的像素点的颜色都被更改成
2
。 - 注意,右下角的像素没有更改为
2
,因为它不属于初始坐标点的周围区域。
- 初始坐标点位于图像的正中间,坐标
- 输入:
六【题目提示】
image
和image[0]
的长度均在范围[1, 50]
内。- 初始坐标点
(sr,sc)
满足0 <= sr < image.length
和0 <= sc < image[0].length
。 image[i][j]
和newColor
表示的颜色值在范围[0, 65535]
内。
七【解题思路】
- 这道题的思路还是比较经典的,使用广度优先算法去寻找与目标点颜色相同的点,然后对其赋值即可,只不过有些细节需要注意
- 要正确的设置上下左右四个方向
- 如果目标点颜色和目标颜色相同,可以直接返回传入的二维数组
- 边界条件不能判断出错
- 正确的赋值,不要搞混颜色
八【时间频度】
- 时间复杂度: O ( n × m ) O(n × m) O(n×m),其中 n n n和 m m m分别为传入的二维数组的行数和列数
- 空间复杂度: O ( n × m ) O(n × m) O(n×m),其中 n n n和 m m m分别为传入的二维数组的行数和列数
九【代码实现】
- Java语言版
class Solution {
// 初始化上下左右四个方向
int[] dx = {1, 0, 0, -1};
int[] dy = {0, 1, -1, 0};
public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
// 获取原始颜色
int originColor = image[sr][sc];
// 如果当前颜色和目标颜色相同直接返回
if (originColor == newColor) {
return image;
}
// 获取初始信息
int row = image.length;
int col = image[0].length;
// 初始化队列
Queue<int[]> queue = new LinkedList<int[]>();
queue.offer(new int[]{sr, sc});
image[sr][sc] = newColor;
// 开始使用广度优先搜索进行颜色填充
while (!queue.isEmpty()) {
int[] pos = queue.poll();
int x = pos[0];
int y = pos[1];
for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];
if (newX >= 0 && newX < row && newY >= 0 && newY < col && image[newX][newY] == originColor) {
queue.offer(new int[]{newX, newY});
image[newX][newY] = newColor;
}
}
}
// 返回结果
return image;
}
}
- Python语言版
class Solution:
def floodFill(self, image: List[List[int]], sr: int, sc: int, newColor: int) -> List[List[int]]:
# 保存初始颜色
originColor = image[sr][sc]
# 如果当前颜色和目标颜色相同,直接返回
if originColor == newColor:
return image
# 获取初始值
row = len(image)
col = len(image[0])
# 初始化队列
queue = collections.deque([(sr, sc)])
image[sr][sc] = newColor
# 使用广度优先算法填充颜色
while queue:
x, y = queue.popleft()
for new_x, new_y in [(x - 1, y), (x + 1, y), (x, y -1), (x, y + 1)]:
if new_x >= 0 and new_x < row and new_y >= 0 and new_y < col and image[new_x][new_y] == originColor:
queue.append((new_x, new_y))
image[new_x][new_y] = newColor
# 返回结果
return image
- C语言版
// 设置上下左右四个方向
const int dx[4] = {1, 0, 0, -1};
const int dy[4] = {0, 1, -1, 0};
int** floodFill(int** image, int imageSize, int* imageColSize, int sr, int sc, int newColor, int* returnSize, int** returnColumnSizes){
// 初始化值
int row = imageSize;
int col = imageColSize[0];
int n = row * col;
// 设置返回数据的行和列数
*returnSize = row;
*returnColumnSizes = (int *)malloc(row * sizeof(int));
for (int i = 0; i < row; i++)
{
(*returnColumnSizes)[i] = col;
}
// 如果起始点已经是新颜色,直接返回
if (newColor == image[sr][sc])
{
return image;
}
// 初始化队列
int** queue = (int **)malloc(sizeof(int*) * n);
for (int i = 0; i < n; i++)
{
queue[i] = (int *)malloc(sizeof(int) * 2);
}
int rear = 0;
int front = 0;
// 初始坐标点入队列
queue[rear][0] = sr;
queue[rear++][1] = sc;
// 保存初始颜色
int originalColor = image[sr][sc];
// 初始坐标点填充新颜色
image[sr][sc] = newColor;
// 开始使用广度优先算法进行颜色填充
while (front != rear)
{
int x = queue[front][0];
int y = queue[front++][1];
for (int i = 0; i < 4; i++)
{
int newX = x + dx[i];
int newY = y + dy[i];
if (newX >= 0 && newX < row && newY >= 0 && newY < col && image[newX][newY] == originalColor)
{
queue[rear][0] = newX;
queue[rear++][1] = newY;
image[newX][newY] = newColor;
}
}
}
// 释放队列内存
for (int i = 0; i < n; i++) {
free(queue[i]);
}
free(queue);
return image;
}
十【提交结果】
-
Java语言版
-
Python语言版
-
C语言版