🧠
Brute Force (Pure Recursion DFS)
💡 Starting with a simple recursive DFS helps understand the problem as exploring connected nodes in a graph. It is intuitive but can cause stack overflow on large inputs.
Intuition
From the starting pixel, recursively visit all 4-directionally connected pixels with the same original color and change their color to the new color.
Algorithm
- Check if the starting pixel's color is already the new color; if yes, return the image as is.
- Store the original color of the starting pixel.
- Define a recursive DFS function that changes the color of the current pixel and recursively calls itself on valid neighbors with the original color.
- Call the DFS function starting from (sr, sc) and return the modified image.
💡 The recursion explores neighbors deeply before backtracking, which can be tricky to visualize but matches the problem's connectedness requirement.
from typing import List
def floodFill(image: List[List[int]], sr: int, sc: int, newColor: int) -> List[List[int]]:
original_color = image[sr][sc]
if original_color == newColor:
return image
rows, cols = len(image), len(image[0])
def dfs(r, c):
if r < 0 or r >= rows or c < 0 or c >= cols:
return
if image[r][c] != original_color:
return
image[r][c] = newColor
dfs(r+1, c)
dfs(r-1, c)
dfs(r, c+1)
dfs(r, c-1)
dfs(sr, sc)
return image
# Example usage:
if __name__ == '__main__':
img = [[1,1,1],[1,1,0],[1,0,1]]
print(floodFill(img, 1, 1, 2))
Line Notes
original_color = image[sr][sc]Capture the color to replace to avoid changing pixels of other colors
if original_color == newColor:Avoid infinite recursion if the color is already the target color
def dfs(r, c):Define recursive function to explore connected pixels
if r < 0 or r >= rows or c < 0 or c >= cols:Boundary check to prevent index errors
if image[r][c] != original_color:Stop recursion if pixel color differs from original
image[r][c] = newColorChange the pixel color to newColor
dfs(r+1, c)Recurse downwards
dfs(r-1, c)Recurse upwards
dfs(r, c+1)Recurse rightwards
dfs(r, c-1)Recurse leftwards
dfs(sr, sc)Start DFS from the starting pixel
return imageReturn the modified image after flood fill
import java.util.*;
public class FloodFill {
public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
int originalColor = image[sr][sc];
if (originalColor == newColor) return image;
int rows = image.length, cols = image[0].length;
dfs(image, sr, sc, originalColor, newColor, rows, cols);
return image;
}
private void dfs(int[][] image, int r, int c, int originalColor, int newColor, int rows, int cols) {
if (r < 0 || r >= rows || c < 0 || c >= cols) return;
if (image[r][c] != originalColor) return;
image[r][c] = newColor;
dfs(image, r + 1, c, originalColor, newColor, rows, cols);
dfs(image, r - 1, c, originalColor, newColor, rows, cols);
dfs(image, r, c + 1, originalColor, newColor, rows, cols);
dfs(image, r, c - 1, originalColor, newColor, rows, cols);
}
public static void main(String[] args) {
FloodFill ff = new FloodFill();
int[][] img = {{1,1,1},{1,1,0},{1,0,1}};
int[][] res = ff.floodFill(img, 1, 1, 2);
System.out.println(Arrays.deepToString(res));
}
}
Line Notes
int originalColor = image[sr][sc];Store original color to identify pixels to change
if (originalColor == newColor) return image;Prevent unnecessary work and infinite recursion
private void dfs(...)Recursive helper to explore connected pixels
if (r < 0 || r >= rows || c < 0 || c >= cols) return;Boundary check to avoid invalid indices
if (image[r][c] != originalColor) return;Stop recursion if pixel color differs
image[r][c] = newColor;Change pixel color
dfs(image, r + 1, c, ...);Explore downward neighbor
dfs(image, r - 1, c, ...);Explore upward neighbor
dfs(image, r, c + 1, ...);Explore right neighbor
dfs(image, r, c - 1, ...);Explore left neighbor
public static void main(String[] args)Driver code to test the flood fill
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
void dfs(vector<vector<int>>& image, int r, int c, int originalColor, int newColor, int rows, int cols) {
if (r < 0 || r >= rows || c < 0 || c >= cols) return;
if (image[r][c] != originalColor) return;
image[r][c] = newColor;
dfs(image, r + 1, c, originalColor, newColor, rows, cols);
dfs(image, r - 1, c, originalColor, newColor, rows, cols);
dfs(image, r, c + 1, originalColor, newColor, rows, cols);
dfs(image, r, c - 1, originalColor, newColor, rows, cols);
}
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
int originalColor = image[sr][sc];
if (originalColor == newColor) return image;
int rows = image.size(), cols = image[0].size();
dfs(image, sr, sc, originalColor, newColor, rows, cols);
return image;
}
};
int main() {
Solution sol;
vector<vector<int>> img = {{1,1,1},{1,1,0},{1,0,1}};
vector<vector<int>> res = sol.floodFill(img, 1, 1, 2);
for (auto &row : res) {
for (auto &val : row) cout << val << ' ';
cout << '\n';
}
return 0;
}
Line Notes
void dfs(vector<vector<int>>& image, int r, int c, int originalColor, int newColor, int rows, int cols)Recursive DFS helper to explore connected pixels
if (r < 0 || r >= rows || c < 0 || c >= cols) return;Boundary check to avoid invalid access
if (image[r][c] != originalColor) return;Stop recursion if pixel color differs
image[r][c] = newColor;Change pixel color to newColor
dfs(image, r + 1, c, ...);Explore downward neighbor
dfs(image, r - 1, c, ...);Explore upward neighbor
dfs(image, r, c + 1, ...);Explore right neighbor
dfs(image, r, c - 1, ...);Explore left neighbor
int originalColor = image[sr][sc];Store original color to identify pixels to change
if (originalColor == newColor) return image;Avoid infinite recursion if colors match
int main()Driver code to test the flood fill implementation
function floodFill(image, sr, sc, newColor) {
const originalColor = image[sr][sc];
if (originalColor === newColor) return image;
const rows = image.length, cols = image[0].length;
function dfs(r, c) {
if (r < 0 || r >= rows || c < 0 || c >= cols) return;
if (image[r][c] !== originalColor) return;
image[r][c] = newColor;
dfs(r + 1, c);
dfs(r - 1, c);
dfs(r, c + 1);
dfs(r, c - 1);
}
dfs(sr, sc);
return image;
}
// Example usage:
const img = [[1,1,1],[1,1,0],[1,0,1]];
console.log(floodFill(img, 1, 1, 2));
Line Notes
const originalColor = image[sr][sc];Capture the original color to identify pixels to change
if (originalColor === newColor) return image;Prevent infinite recursion if color is already newColor
function dfs(r, c)Recursive DFS helper to explore connected pixels
if (r < 0 || r >= rows || c < 0 || c >= cols) return;Boundary check to avoid invalid indices
if (image[r][c] !== originalColor) return;Stop recursion if pixel color differs
image[r][c] = newColor;Change pixel color to newColor
dfs(r + 1, c);Explore downward neighbor
dfs(r - 1, c);Explore upward neighbor
dfs(r, c + 1);Explore right neighbor
dfs(r, c - 1);Explore left neighbor
dfs(sr, sc);Start DFS from the starting pixel
return image;Return the modified image after flood fill
TimeO(N) where N is the number of pixels in the image
SpaceO(N) due to recursion stack in worst case when all pixels are connected
Each pixel is visited at most once, but recursion stack can grow to size of connected region
💡 For a 50x50 image, this means at most 2500 pixels visited and recursion depth up to 2500, which may cause stack overflow in some languages.
Interview Verdict: Accepted
This approach works well for small to medium inputs but risks stack overflow on large connected regions.