Flood Fill Algorithm

01 Nov, 2021
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 0 1 1 1 1 1 3 1 1 1 1 1 1 1 3 3 1 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++
Java
Python3
C#
Javascript
// C++ implementation of the approach#include <bits/stdc++.h>using namespace std; // Function that returns true if// the given pixel is validbool 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 functionvoid floodFill(int screen[][8], int m, int n, int x, int y, int prevC, int newC){    vector<pair<int,int>> queue;     // Append the position of starting    // pixel of the component    pair<int,int> 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<int,int> 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 implementation of the approachimport 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<Point> queue = new Vector<Point>();           // 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 implementation of the approach # Function that returns true if# the given pixel is validdef 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 functiondef 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 codescreen =[[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 displaym = len(screen) # Column of the displayn = len(screen[0]) # Co-ordinate provided by the userx = 4y = 4 # Current color at that co-ordinateprevC = screen[x][y] # New color that has to be fillednewC = 3 floodFill(screen, m, n, x, y, prevC, newC)  # Printing the updated screenfor i in range(m):    for j in range(n):        print(screen[i][j], end =' ')    print()
// C# implementation of the approachusing 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<Tuple<int,int>> queue = new List<Tuple<int,int>>();          // Append the position of starting        // pixel of the component        queue.Add(new Tuple<int,int>(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<int,int> 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<int,int>(posX + 1, posY));            }              if(isValid(screen, m, n, posX-1, posY, prevC, newC))            {                screen[posX-1,posY]= newC;                queue.Add(new Tuple<int,int>(posX-1, posY));            }              if(isValid(screen, m, n, posX, posY + 1, prevC, newC))            {                screen[posX,posY + 1]= newC;                queue.Add(new Tuple<int,int>(posX, posY + 1));            }              if(isValid(screen, m, n, posX, posY-1, prevC, newC))            {                screen[posX,posY-1]= newC;                queue.Add(new Tuple<int,int>(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.
<script>    // Javascript implementation of the approach         // Function that returns true if    // the given pixel is valid    function isValid(screen, m, n, x, y, prevC, newC)    {        if(x<0 || x>= m || y<0 || y>= n || screen[x][y]!= prevC           || screen[x][y]== newC)            return false;        return true;    }      // FloodFill function    function floodFill(screen, m, n, x, y, prevC, newC)    {        let queue = [];         // Append the position of starting        // pixel of the component        queue.push([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.length > 0)        {            // Dequeue the front node            currPixel = queue[queue.length - 1];            queue.pop();             let posX = currPixel[0];            let 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.push([posX + 1, posY]);            }             if(isValid(screen, m, n, posX-1, posY, prevC, newC))            {                screen[posX-1][posY]= newC;                queue.push([posX-1, posY]);            }             if(isValid(screen, m, n, posX, posY + 1, prevC, newC))            {                screen[posX][posY + 1]= newC;                queue.push([posX, posY + 1]);            }             if(isValid(screen, m, n, posX, posY-1, prevC, newC))            {                screen[posX][posY-1]= newC;                queue.push([posX, posY-1]);            }        }    }         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 = screen.length;     // Column of the display    let n = screen[0].length;     // 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, m, n, x, y, prevC, newC);      // Printing the updated screen    for(let i = 0; i < m; i++)    {        for(let j = 0; j < n; j++)        {            document.write(screen[i][j] + " ");        }        document.write("</br>");    }         // This code is contributed by divyesh072019.</script>
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
 
DFS Approach: Similarly DFS approach can be used to implement the Flood Fill algorithm as well. 
sweetyty
divyesh072019
divyeshrabadiya07
mukesh07
suresh07
BFS
Google
Algorithms
Graph
Matrix
Recursion
Google
Recursion
Matrix
Graph
BFS
Algorithms
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
DSA Sheet by Love Babbar
SDE SHEET - A Complete Guide for SDE Preparation
What is Hashing | A Complete Tutorial
Understanding Time Complexity with Simple Examples
Find if there is a path between two vertices in an undirected graph
Dijkstra's shortest path algorithm | Greedy Algo-7
Prim’s Minimum Spanning Tree (MST) | Greedy Algo-5
Graph and its representations
Topological Sorting
Find if there is a path between two vertices in a directed graph