Open in App
Not now

Flood Fill Algorithm

• Difficulty Level : Medium
• Last Updated : 18 Feb, 2023

Given a 2D screen arr[][] where each arr[i][j] is an integer representing the color of that pixel, also given the location of a pixel (X, Y) and a color C, the task is to replace the color of the given pixel and all the adjacent same-colored pixels with the given color.

Example:

Input: arr[][] = {
{1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 0, 0},
{1, 0, 0, 1, 1, 0, 1, 1},
{1, 2, 2, 2, 2, 0, 1, 0},
{1, 1, 1, 2, 2, 0, 1, 0},
{1, 1, 1, 2, 2, 2, 2, 0},
{1, 1, 1, 1, 1, 2, 1, 1},
{1, 1, 1, 1, 1, 2, 2, 1}}
X = 4, Y = 4, C = 3
Output:
1 1 1 1 1 1 1 1
1 1 1 1 1 1 0 0
1 0 0 1 1 0 1 1
1 3 3 3 3 0 1 0
1 1 1 3 3 0 1 0
1 1 1 3 3 3 3
1 1 1 1 1 3 1 1
1 1 1 1 1 3 3
Explanation:
The values in the given 2D screen indicate colors of the pixels. X and Y are coordinates of the brush, C is the color that should replace the previous color on screen[X][Y] and all surrounding pixels with the same color. Hence all the 2 are replaced with 3.

BFS Approach: The idea is to use BFS traversal to replace the color with the new color.

• Create an empty queue lets say Q.
• Push the starting location of the pixel as given in the input and apply replacement color to it.
• Iterate until Q is not empty and pop the front node (pixel position).
• Check the pixels adjacent to the current pixel and push into the queue if valid (had not been colored with replacement color and have the same color as the old color).

Below is the implementation of the above approach:

C++

 // C++ implementation of the approach #include using namespace std;   // Function that returns true if // the given pixel is valid bool isValid(int screen[][8], int m, int n, int x, int y, int prevC, int newC) {     if(x < 0 || x >= m || y < 0 || y >= n || screen[x][y] != prevC        || screen[x][y]== newC)         return false;     return true; }     // FloodFill function void floodFill(int screen[][8], int m, int n, int x, int y, int prevC, int newC) {     vector> queue;       // Append the position of starting     // pixel of the component     pair p(x,y);     queue.push_back(p);       // Color the pixel with the new color     screen[x][y] = newC;       // While the queue is not empty i.e. the     // whole component having prevC color     // is not colored with newC color     while(queue.size() > 0)     {         // Dequeue the front node         pair currPixel = queue[queue.size() - 1];         queue.pop_back();           int posX = currPixel.first;         int posY = currPixel.second;           // Check if the adjacent         // pixels are valid         if(isValid(screen, m, n, posX + 1, posY, prevC, newC))         {             // Color with newC             // if valid and enqueue             screen[posX + 1][posY] = newC;             p.first = posX + 1;             p.second = posY;             queue.push_back(p);         }           if(isValid(screen, m, n, posX-1, posY, prevC, newC))         {             screen[posX-1][posY]= newC;             p.first = posX-1;             p.second = posY;             queue.push_back(p);         }           if(isValid(screen, m, n, posX, posY + 1, prevC, newC))         {             screen[posX][posY + 1]= newC;             p.first = posX;             p.second = posY + 1;             queue.push_back(p);         }           if(isValid(screen, m, n, posX, posY-1, prevC, newC))         {             screen[posX][posY-1]= newC;             p.first = posX;             p.second = posY-1;             queue.push_back(p);         }     } }       int main() {     int screen[][8] ={     {1, 1, 1, 1, 1, 1, 1, 1},     {1, 1, 1, 1, 1, 1, 0, 0},     {1, 0, 0, 1, 1, 0, 1, 1},     {1, 2, 2, 2, 2, 0, 1, 0},     {1, 1, 1, 2, 2, 0, 1, 0},     {1, 1, 1, 2, 2, 2, 2, 0},     {1, 1, 1, 1, 1, 2, 1, 1},     {1, 1, 1, 1, 1, 2, 2, 1}};          // Row of the display     int m = 8;          // Column of the display     int n = 8;          // Co-ordinate provided by the user     int x = 4;     int y = 4;          // Current color at that co-ordinate     int prevC = screen[x][y];          // New color that has to be filled     int newC = 3;     floodFill(screen, m, n, x, y, prevC, newC);          // Printing the updated screen     for(int i = 0; i < m; i++)     {         for(int j = 0; j < n; j++)         {             cout << screen[i][j] << " ";         }         cout << endl;     }       return 0; }   // This code is contributed by suresh07.

Java

 // Java implementation of the approach import java.util.*; import java.awt.Point; public class Main {     // Function that returns true if     // the given pixel is valid     static boolean isValid(int[][] screen, int m, int n, int x, int y, int prevC, int newC)     {         if(x < 0 || x >= m || y < 0 || y >= n || screen[x][y] != prevC            || screen[x][y]== newC)             return false;         return true;     }             // FloodFill function     static void floodFill(int[][] screen, int m, int n, int x, int y, int prevC, int newC)     {         Vector queue = new Vector();             // Append the position of starting         // pixel of the component         queue.add(new Point(x, y));             // Color the pixel with the new color         screen[x][y] = newC;             // While the queue is not empty i.e. the         // whole component having prevC color         // is not colored with newC color         while(queue.size() > 0)         {             // Dequeue the front node             Point currPixel = queue.get(queue.size() - 1);             queue.remove(queue.size() - 1);                 int posX = currPixel.x;             int posY = currPixel.y;                 // Check if the adjacent             // pixels are valid             if(isValid(screen, m, n, posX + 1, posY, prevC, newC))             {                 // Color with newC                 // if valid and enqueue                 screen[posX + 1][posY] = newC;                 queue.add(new Point(posX + 1, posY));             }                 if(isValid(screen, m, n, posX-1, posY, prevC, newC))             {                 screen[posX-1][posY]= newC;                 queue.add(new Point(posX-1, posY));             }                 if(isValid(screen, m, n, posX, posY + 1, prevC, newC))             {                 screen[posX][posY + 1]= newC;                 queue.add(new Point(posX, posY + 1));             }                 if(isValid(screen, m, n, posX, posY-1, prevC, newC))             {                 screen[posX][posY-1]= newC;                 queue.add(new Point(posX, posY-1));             }         }     }           public static void main(String[] args) {         int[][] screen ={         {1, 1, 1, 1, 1, 1, 1, 1},         {1, 1, 1, 1, 1, 1, 0, 0},         {1, 0, 0, 1, 1, 0, 1, 1},         {1, 2, 2, 2, 2, 0, 1, 0},         {1, 1, 1, 2, 2, 0, 1, 0},         {1, 1, 1, 2, 2, 2, 2, 0},         {1, 1, 1, 1, 1, 2, 1, 1},         {1, 1, 1, 1, 1, 2, 2, 1}};                 // Row of the display         int m = screen.length;                 // Column of the display         int n = screen.length;                 // Co-ordinate provided by the user         int x = 4;         int y = 4;                 // Current color at that co-ordinate         int prevC = screen[x][y];                 // New color that has to be filled         int newC = 3;         floodFill(screen, m, n, x, y, prevC, newC);                 // Printing the updated screen         for(int i = 0; i < m; i++)         {             for(int j = 0; j < n; j++)             {                 System.out.print(screen[i][j] + " ");             }             System.out.println();         }     } }   // This code is contributed by mukesh07.

Python3

 # Python3 implementation of the approach   # Function that returns true if # the given pixel is valid def isValid(screen, m, n, x, y, prevC, newC):     if x<0 or x>= m\        or y<0 or y>= n or\        screen[x][y]!= prevC\        or screen[x][y]== newC:         return False     return True     # FloodFill function def floodFill(screen,              m, n, x,              y, prevC, newC):     queue = []           # Append the position of starting     # pixel of the component     queue.append([x, y])       # Color the pixel with the new color     screen[x][y] = newC       # While the queue is not empty i.e. the     # whole component having prevC color     # is not colored with newC color     while queue:                   # Dequeue the front node         currPixel = queue.pop()                   posX = currPixel[0]         posY = currPixel[1]                   # Check if the adjacent         # pixels are valid         if isValid(screen, m, n,                  posX + 1, posY,                          prevC, newC):                           # Color with newC             # if valid and enqueue             screen[posX + 1][posY] = newC             queue.append([posX + 1, posY])                   if isValid(screen, m, n,                      posX-1, posY,                          prevC, newC):             screen[posX-1][posY]= newC             queue.append([posX-1, posY])                   if isValid(screen, m, n,                  posX, posY + 1,                          prevC, newC):             screen[posX][posY + 1]= newC             queue.append([posX, posY + 1])                   if isValid(screen, m, n,                      posX, posY-1,                          prevC, newC):             screen[posX][posY-1]= newC             queue.append([posX, posY-1])       # Driver code screen =[ [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 0, 0], [1, 0, 0, 1, 1, 0, 1, 1], [1, 2, 2, 2, 2, 0, 1, 0], [1, 1, 1, 2, 2, 0, 1, 0], [1, 1, 1, 2, 2, 2, 2, 0], [1, 1, 1, 1, 1, 2, 1, 1], [1, 1, 1, 1, 1, 2, 2, 1],     ]       # Row of the display m = len(screen)   # Column of the display n = len(screen[0])   # Co-ordinate provided by the user x = 4 y = 4   # Current color at that co-ordinate prevC = screen[x][y]   # New color that has to be filled newC = 3   floodFill(screen, m, n, x, y, prevC, newC)     # Printing the updated screen for i in range(m):     for j in range(n):         print(screen[i][j], end =' ')     print()

C#

 // C# implementation of the approach using System; using System.Collections.Generic; class GFG {           // Function that returns true if     // the given pixel is valid     static bool isValid(int[,] screen, int m, int n, int x, int y, int prevC, int newC)     {         if(x < 0 || x >= m || y < 0 || y >= n || screen[x, y] != prevC            || screen[x,y]== newC)             return false;         return true;     }           // FloodFill function     static void floodFill(int[,] screen, int m, int n, int x, int y, int prevC, int newC)     {         List> queue = new List>();            // Append the position of starting         // pixel of the component         queue.Add(new Tuple(x, y));            // Color the pixel with the new color         screen[x,y] = newC;            // While the queue is not empty i.e. the         // whole component having prevC color         // is not colored with newC color         while(queue.Count > 0)         {             // Dequeue the front node             Tuple currPixel = queue[queue.Count - 1];             queue.RemoveAt(queue.Count - 1);                int posX = currPixel.Item1;             int posY = currPixel.Item2;                // Check if the adjacent             // pixels are valid             if(isValid(screen, m, n, posX + 1, posY, prevC, newC))             {                 // Color with newC                 // if valid and enqueue                 screen[posX + 1,posY] = newC;                 queue.Add(new Tuple(posX + 1, posY));             }                if(isValid(screen, m, n, posX-1, posY, prevC, newC))             {                 screen[posX-1,posY]= newC;                 queue.Add(new Tuple(posX-1, posY));             }                if(isValid(screen, m, n, posX, posY + 1, prevC, newC))             {                 screen[posX,posY + 1]= newC;                 queue.Add(new Tuple(posX, posY + 1));             }                if(isValid(screen, m, n, posX, posY-1, prevC, newC))             {                 screen[posX,posY-1]= newC;                 queue.Add(new Tuple(posX, posY-1));             }         }     }         static void Main() {     int[,] screen ={     {1, 1, 1, 1, 1, 1, 1, 1},     {1, 1, 1, 1, 1, 1, 0, 0},     {1, 0, 0, 1, 1, 0, 1, 1},     {1, 2, 2, 2, 2, 0, 1, 0},     {1, 1, 1, 2, 2, 0, 1, 0},     {1, 1, 1, 2, 2, 2, 2, 0},     {1, 1, 1, 1, 1, 2, 1, 1},     {1, 1, 1, 1, 1, 2, 2, 1}};        // Row of the display     int m = screen.GetLength(0);        // Column of the display     int n = screen.GetLength(1);        // Co-ordinate provided by the user     int x = 4;     int y = 4;        // Current color at that co-ordinate     int prevC = screen[x,y];        // New color that has to be filled     int newC = 3;     floodFill(screen, m, n, x, y, prevC, newC);        // Printing the updated screen     for(int i = 0; i < m; i++)     {         for(int j = 0; j < n; j++)         {             Console.Write(screen[i,j] + " ");         }         Console.WriteLine();     }   } }   // This code is contributed by divyeshrabadiya07.

Javascript



Output

1 1 1 1 1 1 1 1
1 1 1 1 1 1 0 0
1 0 0 1 1 0 1 1
1 3 3 3 3 0 1 0
1 1 1 3 3 0 1 0
1 1 1 3 3 3 3 0
1 1 1 1 1 3 1 1
1 1 1 1 1 3 3 1

Time Complexity: O(N*M)
Auxiliary Space: O(N*M)

An Approach using DFS:

• Change the color of source row and source column with given color
• Do dfs in four direction

Below is the implementation of the above approach:

C++

 // C++ implementation of the approach #include using namespace std;   // Floodfill function void floodFill(vector >& screen, int sr, int sc,                int row, int col, int source, int color) {     // Condition for checking out of bounds     if (sr < 0 || sr >= row || sc < 0 || sc >= col)         return;       if (screen[sr][sc] != source)         return;         screen[sr][sc] = color;     floodFill(screen, sr - 1, sc, row, col, source,               color); // left     floodFill(screen, sr + 1, sc, row, col, source,               color); // right     floodFill(screen, sr, sc + 1, row, col, source,               color); // top     floodFill(screen, sr, sc - 1, row, col, source,               color); // bottom }   // Driver code int main() {     vector > screen         = { { 1, 1, 1, 1, 1, 1, 1, 1 },             { 1, 1, 1, 1, 1, 1, 0, 0 },             { 1, 0, 0, 1, 1, 0, 1, 1 },             { 1, 2, 2, 2, 2, 0, 1, 0 },             { 1, 1, 1, 2, 2, 0, 1, 0 },             { 1, 1, 1, 2, 2, 2, 2, 0 },             { 1, 1, 1, 1, 1, 2, 1, 1 },             { 1, 1, 1, 1, 1, 2, 2, 1 } };       // Row of the display     int m = 8;       // Column of the display     int n = 8;       // Co-ordinate provided by the user     int x = 4;     int y = 4;       // Current color at that co-ordinate     int prevC = screen[x][y];       // New color that has to be filled     int newC = 3;       floodFill(screen, x, y, m, n, prevC, newC);       // Printing the updated screen     for (int i = 0; i < m; i++) {         for (int j = 0; j < n; j++) {             cout << screen[i][j] << " ";         }         cout << endl;     }       return 0; }   // This code is contributed by hkdass001.

Java

 import java.util.ArrayList;   public class FloodFill { // Floodfill function public static void floodFill(int[][] screen, int sr, int sc, int row, int col, int source, int color) { // Condition for checking out of bounds if (sr < 0 || sr >= row || sc < 0 || sc >= col) return;       if (screen[sr][sc] != source)         return;       screen[sr][sc] = color;     floodFill(screen, sr - 1, sc, row, col, source, color); // left     floodFill(screen, sr + 1, sc, row, col, source, color); // right     floodFill(screen, sr, sc + 1, row, col, source, color); // top     floodFill(screen, sr, sc - 1, row, col, source, color); // bottom }   public static void main(String[] args) {     int[][] screen = {{1, 1, 1, 1, 1, 1, 1, 1},             {1, 1, 1, 1, 1, 1, 0, 0},             {1, 0, 0, 1, 1, 0, 1, 1},             {1, 2, 2, 2, 2, 0, 1, 0},             {1, 1, 1, 2, 2, 0, 1, 0},             {1, 1, 1, 2, 2, 2, 2, 0},             {1, 1, 1, 1, 1, 2, 1, 1},             {1, 1, 1, 1, 1, 2, 2, 1}};       // Row of the display     int m = 8;       // Column of the display     int n = 8;       // Co-ordinate provided by the user     int x = 4;     int y = 4;       // Current color at that co-ordinate     int prevC = screen[x][y];       // New color that has to be filled     int newC = 3;       floodFill(screen, x, y, m, n, prevC, newC);       // Printing the updated screen     for (int i = 0; i < m; i++) {         for (int j = 0; j < n; j++) {             System.out.print(screen[i][j] + " ");         }         System.out.println();     } }   }

Python3

 from typing import List, Tuple   def flood_fill(screen: List[List[int]], sr: int, sc: int, row: int, col: int, source: int, color: int) -> None:     # Condition for checking out of bounds     if sr < 0 or sr >= row or sc < 0 or sc >= col:         return       if screen[sr][sc] != source:         return       screen[sr][sc] = color     flood_fill(screen, sr - 1, sc, row, col, source, color) # left     flood_fill(screen, sr + 1, sc, row, col, source, color) # right     flood_fill(screen, sr, sc + 1, row, col, source, color) # top     flood_fill(screen, sr, sc - 1, row, col, source, color) # bottom   if __name__ == "__main__":     screen = [         [1, 1, 1, 1, 1, 1, 1, 1],         [1, 1, 1, 1, 1, 1, 0, 0],         [1, 0, 0, 1, 1, 0, 1, 1],         [1, 2, 2, 2, 2, 0, 1, 0],         [1, 1, 1, 2, 2, 0, 1, 0],         [1, 1, 1, 2, 2, 2, 2, 0],         [1, 1, 1, 1, 1, 2, 1, 1],         [1, 1, 1, 1, 1, 2, 2, 1]     ]       # Row of the display     m = 8       # Column of the display     n = 8       # Coordinate provided by the user     x = 4     y = 4       # Current color at that coordinate     prevC = screen[x][y]       # New color that has to be filled     newC = 3       flood_fill(screen, x, y, m, n, prevC, newC)       # Printing the updated screen     for i in range(m):         for j in range(n):             print(screen[i][j], end=" ")         print()

Javascript

 // JavaScript implementation of the approach     // Floodfill function function floodFill(screen, sr, sc, row, col, source, color) {     // Condition for checking out of bounds     if (sr < 0 || sr >= row || sc < 0 || sc >= col) return;       if (screen[sr][sc] != source) return;       screen[sr][sc] = color;     floodFill(screen, sr - 1, sc, row, col, source, color); // left     floodFill(screen, sr + 1, sc, row, col, source, color); // right     floodFill(screen, sr, sc + 1, row, col, source, color); // top     floodFill(screen, sr, sc - 1, row, col, source, color); // bottom }   // Driver code let screen = [  [ 1, 1, 1, 1, 1, 1, 1, 1 ],                 [ 1, 1, 1, 1, 1, 1, 0, 0 ],                 [ 1, 0, 0, 1, 1, 0, 1, 1 ],                 [ 1, 2, 2, 2, 2, 0, 1, 0 ],                 [ 1, 1, 1, 2, 2, 0, 1, 0 ],                 [ 1, 1, 1, 2, 2, 2, 2, 0 ],                 [ 1, 1, 1, 1, 1, 2, 1, 1 ],                 [ 1, 1, 1, 1, 1, 2, 2, 1 ] ];     // Row of the display let m = 8;   // Column of the display let n = 8;   // Co-ordinate provided by the user let x = 4; let y = 4;   // Current color at that co-ordinate let prevC = screen[x][y];   // New color that has to be filled let newC = 3;   floodFill(screen, x, y, m, n, prevC, newC);   // Printing the updated screen for (let i = 0; i < m; i++) {     let temp = "";     for (let j = 0; j < n; j++) {            document.write(screen[i][j] + " ");     }     document.write("
"); }     // This code is contributed by Gautam goel

C#

 using System;   namespace FloodFill {     class Program     {         static void Main(string[] args)         {             int[,] screen =             {                 {1, 1, 1, 1, 1, 1, 1, 1},                 {1, 1, 1, 1, 1, 1, 0, 0},                 {1, 0, 0, 1, 1, 0, 1, 1},                 {1, 2, 2, 2, 2, 0, 1, 0},                 {1, 1, 1, 2, 2, 0, 1, 0},                 {1, 1, 1, 2, 2, 2, 2, 0},                 {1, 1, 1, 1, 1, 2, 1, 1},                 {1, 1, 1, 1, 1, 2, 2, 1}             };               // Dimensions of the screen             int m = 8;             int n = 8;               // Coordinates provided by the user             int x = 4;             int y = 4;               // Current color at the given coordinate             int prevC = screen[x, y];               // New color to fill             int newC = 3;               FloodFill(screen, x, y, m, n, prevC, newC);               // Printing the updated screen             for (int i = 0; i < m; i++)             {                 for (int j = 0; j < n; j++)                 {                     Console.Write(screen[i, j] + " ");                 }                 Console.WriteLine();             }               Console.ReadKey();         }           // Flood fill function         static void FloodFill(int[,] screen, int sr, int sc, int row, int col, int source, int color)         {             // Check for out of bounds             if (sr < 0 || sr >= row || sc < 0 || sc >= col)                 return;               // Check if the current pixel is not equal to the source color             if (screen[sr, sc] != source)                 return;               screen[sr, sc] = color;               // Recursively fill the surrounding pixels             FloodFill(screen, sr - 1, sc, row, col, source, color); // left             FloodFill(screen, sr + 1, sc, row, col, source, color); // right             FloodFill(screen, sr, sc + 1, row, col, source, color); // top             FloodFill(screen, sr, sc - 1, row, col, source, color); // bottom         }     } }

Output

1 1 1 1 1 1 1 1
1 1 1 1 1 1 0 0
1 0 0 1 1 0 1 1
1 3 3 3 3 0 1 0
1 1 1 3 3 0 1 0
1 1 1 3 3 3 3 0
1 1 1 1 1 3 1 1
1 1 1 1 1 3 3 1

Time Complexity: O(m*n)
Auxiliary Space: O(m + n), due to the recursive call stack.

My Personal Notes arrow_drop_up
Related Articles