Before attempting this problem, you should be comfortable with:
Flood fill is like using the paint bucket tool in image editors. Starting from a pixel, we want to change its color and spread to all connected pixels of the same original color. This naturally maps to a graph traversal problem where each pixel is a node connected to its four neighbors.
DFS works well here because we recursively explore as far as possible in one direction before backtracking. By changing the color as we visit each pixel, we mark it as visited, preventing infinite loops. If the new color equals the original, we skip the operation entirely to avoid unnecessary work.
dfs function that takes row and column coordinates.dfs: if out of bounds or the pixel color does not match the original, return.dfs on all four neighbors (up, down, left, right).dfs from the initial coordinates and return the modified image.class Solution:
def floodFill(self, image: List[List[int]], sr: int, sc: int, color: int) -> List[List[int]]:
if image[sr][sc] == color:
return image
m, n = len(image), len(image[0])
dirs = [1,0,-1,0,1]
def dfs(r, c, org):
if not (0 <= r < m) or not (0 <= c < n) or image[r][c] != org:
return
image[r][c] = color
for d in range(4):
dfs(r + dirs[d], c + dirs[d + 1], org)
dfs(sr, sc, image[sr][sc])
return imageWhere is the number of rows and is the number of columns in the image.
BFS explores pixels level by level, processing all pixels at distance 1 from the start before those at distance 2, and so on. While DFS dives deep immediately, BFS spreads outward uniformly. Both achieve the same result for flood fill, but BFS uses a queue instead of the call stack.
The key is to color pixels when adding them to the queue, not when processing them. This prevents adding the same pixel multiple times and keeps the queue size manageable.
image.class Solution:
def floodFill(self, image: List[List[int]], sr: int, sc: int, color: int) -> List[List[int]]:
orig = image[sr][sc]
if orig == color:
return image
m, n = len(image), len(image[0])
q = deque([(sr, sc)])
image[sr][sc] = color
dirs = [(1,0), (-1,0), (0,1), (0,-1)]
while q:
r, c = q.popleft()
for dr, dc in dirs:
nr, nc = r + dr, c + dc
if 0 <= nr < m and 0 <= nc < n and image[nr][nc] == orig:
image[nr][nc] = color
q.append((nr, nc))
return imageWhere is the number of rows and is the number of columns in the image.
If the starting pixel already has the target color, the algorithm will infinitely revisit the same pixels since the color change that normally marks pixels as visited never happens. Always check if originalColor == newColor at the start and return immediately if true.
The flood fill must only spread to pixels matching the original color of the starting pixel. If you check against the current pixel color after already modifying some pixels, you may either skip valid pixels or incorrectly include pixels of the new color. Store the original color in a variable before any modifications.