You are given an image represented by an m x n
grid of integers image
, where image[i][j]
represents the pixel value of the image. You are also given three integers sr
, sc
, and color
. Your task is to perform a flood fill on the image starting from the pixel image[sr][sc]
.
To perform a flood fill:
color
.Return the modified image after performing the flood fill.
Example 1:
image = [[1,1,1],[1,1,0],[1,0,1]], sr = 1, sc = 1, color = 2
Output: [[2,2,2],[2,2,0],[2,0,1]]
From the center of the image with position (sr, sc) = (1, 1)
, all pixels connected by a path of the same color as the starting pixel are colored with the new color. Note the bottom corner is not colored 2, because it is not horizontally or vertically connected to the starting pixel.
Example 2:
image = [[0,0,0],[0,0,0]], sr = 0, sc = 0, color = 0
Output: [[0,0,0],[0,0,0]]
The starting pixel is already colored with 0, which is the same as the target color. Therefore, no changes are made to the image.
This problem requires us to implement the flood fill algorithm. Given a 2D array (image), a starting coordinate (sr, sc), and a color, we need to replace the color of the starting pixel and all connected pixels of the same color with the new color. Let's walk through a couple of approaches.
The most straightforward way to implement flood fill is by using recursion. We start at the given pixel, change its color, and then recursively call the flood fill function on its four neighbors (up, down, left, right) if they have the same original color as the starting pixel.
floodFillUtil(image, row, col, newColor, originalColor)
.floodFillUtil
:
row
or col
are out of bounds, or image[row][col]
is not equal to originalColor
, return.image[row][col]
to newColor
.floodFillUtil
on the four neighboring pixels: (row-1, col)
, (row+1, col)
, (row, col-1)
, (row, col+1)
.floodFillUtil
starting from (sr, sc)
with the original color and the new color.class Solution {
public int[][] floodFill(int[][] image, int sr, int sc, int color) {
int originalColor = image[sr][sc];
if (originalColor == color) {
return image;
}
floodFillUtil(image, sr, sc, color, originalColor);
return image;
}
private void floodFillUtil(int[][] image, int row, int col, int newColor, int originalColor) {
if (row < 0 || row >= image.length || col < 0 || col >= image[0].length || image[row][col] != originalColor) {
return;
}
image[row][col] = newColor;
floodFillUtil(image, row - 1, col, newColor, originalColor);
floodFillUtil(image, row + 1, col, newColor, originalColor);
floodFillUtil(image, row, col - 1, newColor, originalColor);
floodFillUtil(image, row, col + 1, newColor, originalColor);
}
}
In the worst case, we might have to visit every pixel in the image.
In the worst case, the recursion depth can be proportional to the number of pixels if the entire image has the same color, leading to a stack overflow.
To avoid potential stack overflow issues with the recursive approach, especially for large images, we can implement flood fill iteratively using a queue (Breadth-First Search).
(sr, sc)
. Also, store the original color.(row, col)
from the queue.image[row][col]
to newColor
.(row, col)
:
import java.util.LinkedList;
import java.util.Queue;
class Solution {
public int[][] floodFill(int[][] image, int sr, int sc, int color) {
int originalColor = image[sr][sc];
if (originalColor == color) {
return image;
}
int rows = image.length;
int cols = image[0].length;
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{sr, sc});
image[sr][sc] = color; // Initial color change
int[][] directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
while (!queue.isEmpty()) {
int[] pixel = queue.poll();
int row = pixel[0];
int col = pixel[1];
for (int[] dir : directions) {
int newRow = row + dir[0];
int newCol = col + dir[1];
if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols && image[newRow][newCol] == originalColor) {
image[newRow][newCol] = color; // Change color here, before enqueuing
queue.offer(new int[]{newRow, newCol});
}
}
}
return image;
}
}
In the worst case, we might have to visit every pixel in the image.
In the worst case, the queue can contain all the pixels in the image if the entire image has the same color.
sr
and sc
(though constraints say 0 <= sr < m and 0 <= sc < n, so it won't happen).Both the recursive and iterative approaches have the same time complexity O(mn). The iterative version with a queue is generally preferred to avoid stack overflow for larger images. The space complexity is also O(mn) for both approaches in the worst case.