In MS-Paint, when we take the brush to a pixel and click, the color of the region of that pixel is replaced with a new selected color. Following is the problem statement to do this task.
Given a 2D screen, location of a pixel in the screen and a color, replace color of the given pixel and all adjacent same colored pixels with the given color.
Example:
Input: screen[M][N] = {{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, newColor = 3 The values in the given 2D screen indicate colors of the pixels. x and y are coordinates of the brush, newColor is the color that should replace the previous color on screen[x][y] and all surrounding pixels with same color. Output: Screen should be changed to following. screen[M][N] = {{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}, };
This question can be solved using either Recursion or BFS. Both the solutions are discussed below
1:- Using Recursion
The idea is simple, we first replace the color of the current pixel, then recur for 4 surrounding points. The following is a detailed algorithm.
// A recursive function to replace // previous color 'prevC' at '(x, y)' // and all surrounding pixels of (x, y) // with new color 'newC' and floodFil(screen[M][N], x, y, prevC, newC) 1) If x or y is outside the screen, then return. 2) If color of screen[x][y] is not same as prevC, then return 3) Recur for north, south, east and west. floodFillUtil(screen, x+1, y, prevC, newC); floodFillUtil(screen, x-1, y, prevC, newC); floodFillUtil(screen, x, y+1, prevC, newC); floodFillUtil(screen, x, y-1, prevC, newC);
The following is the implementation of the above algorithm.
C++
// A C++ program to implement flood fill algorithm #include<iostream> using namespace std; // Dimentions of paint screen #define M 8 #define N 8 // A recursive function to replace previous color 'prevC' at '(x, y)' // and all surrounding pixels of (x, y) with new color 'newC' and void floodFillUtil( int screen[][N], int x, int y, int prevC, int newC) { // Base cases if (x < 0 || x >= M || y < 0 || y >= N) return ; if (screen[x][y] != prevC) return ; if (screen[x][y] == newC) return ; // Replace the color at (x, y) screen[x][y] = newC; // Recur for north, east, south and west floodFillUtil(screen, x+1, y, prevC, newC); floodFillUtil(screen, x-1, y, prevC, newC); floodFillUtil(screen, x, y+1, prevC, newC); floodFillUtil(screen, x, y-1, prevC, newC); } // It mainly finds the previous color on (x, y) and // calls floodFillUtil() void floodFill( int screen[][N], int x, int y, int newC) { int prevC = screen[x][y]; floodFillUtil(screen, x, y, prevC, newC); } // Driver code int main() { int screen[M][N] = {{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}, }; int x = 4, y = 4, newC = 3; floodFill(screen, x, y, newC); cout << "Updated screen after call to floodFill: \n" ; for ( int i=0; i<M; i++) { for ( int j=0; j<N; j++) cout << screen[i][j] << " " ; cout << endl; } } |
Java
// Java program to implement flood fill algorithm class GFG { // Dimentions of paint screen static int M = 8 ; static int N = 8 ; // A recursive function to replace previous color 'prevC' at '(x, y)' // and all surrounding pixels of (x, y) with new color 'newC' and static void floodFillUtil( int screen[][], int x, int y, int prevC, int newC) { // Base cases if (x < 0 || x >= M || y < 0 || y >= N) return ; if (screen[x][y] != prevC) return ; // Replace the color at (x, y) screen[x][y] = newC; // Recur for north, east, south and west floodFillUtil(screen, x+ 1 , y, prevC, newC); floodFillUtil(screen, x- 1 , y, prevC, newC); floodFillUtil(screen, x, y+ 1 , prevC, newC); floodFillUtil(screen, x, y- 1 , prevC, newC); } // It mainly finds the previous color on (x, y) and // calls floodFillUtil() static void floodFill( int screen[][], int x, int y, int newC) { int prevC = screen[x][y]; floodFillUtil(screen, x, y, prevC, newC); } // Driver code 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 }, }; int x = 4 , y = 4 , newC = 3 ; floodFill(screen, x, y, newC); System.out.println( "Updated screen after call to floodFill: " ); 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 has been contributed by 29AjayKumar |
Python3
# Python3 program to implement # flood fill algorithm # Dimentions of paint screen M = 8 N = 8 # A recursive function to replace # previous color 'prevC' at '(x, y)' # and all surrounding pixels of (x, y) # with new color 'newC' and def floodFillUtil(screen, x, y, prevC, newC): # Base cases if (x < 0 or x > = M or y < 0 or y > = N or screen[x][y] ! = prevC or screen[x][y] = = newC): return # Replace the color at (x, y) screen[x][y] = newC # Recur for north, east, south and west floodFillUtil(screen, x + 1 , y, prevC, newC) floodFillUtil(screen, x - 1 , y, prevC, newC) floodFillUtil(screen, x, y + 1 , prevC, newC) floodFillUtil(screen, x, y - 1 , prevC, newC) # It mainly finds the previous color on (x, y) and # calls floodFillUtil() def floodFill(screen, x, y, newC): prevC = screen[x][y] floodFillUtil(screen, x, y, prevC, newC) # 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 ]] x = 4 y = 4 newC = 3 floodFill(screen, x, y, newC) print ( "Updated screen after call to floodFill:" ) for i in range (M): for j in range (N): print (screen[i][j], end = ' ' ) print () # This code is contributed by Ashutosh450 |
C#
// C# program to implement // flood fill algorithm using System; class GFG { // Dimentions of paint screen static int M = 8; static int N = 8; // A recursive function to replace // previous color 'prevC' at '(x, y)' // and all surrounding pixels of (x, y) // with new color 'newC' and static void floodFillUtil( int [,]screen, int x, int y, int prevC, int newC) { // Base cases if (x < 0 || x >= M || y < 0 || y >= N) return ; if (screen[x, y] != prevC) return ; // Replace the color at (x, y) screen[x, y] = newC; // Recur for north, east, south and west floodFillUtil(screen, x + 1, y, prevC, newC); floodFillUtil(screen, x - 1, y, prevC, newC); floodFillUtil(screen, x, y + 1, prevC, newC); floodFillUtil(screen, x, y - 1, prevC, newC); } // It mainly finds the previous color // on (x, y) and calls floodFillUtil() static void floodFill( int [,]screen, int x, int y, int newC) { int prevC = screen[x, y]; floodFillUtil(screen, x, y, prevC, newC); } // Driver code 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}}; int x = 4, y = 4, newC = 3; floodFill(screen, x, y, newC); Console.WriteLine( "Updated screen after" + "call to floodFill: " ); 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 PrinciRaj1992 |
Updated screen after call to floodFill: 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
Method 2: Using the BFS approach
Algorithm for BFS based approach :
- Create a queue of pairs.
- Insert an initial index given in the queue.
- Mark initial index as visited in vis[][] matrix.
- Until the queue is not empty repeat step 3.1 to 3.6
- Take the front element from the queue
- Pop from the queue
- Store current value/colour at coordinate taken out from queue (precolor)
- Update the value/color of the current index which is taken out from the queue
- Check for all 4 direction i.e (x+1,y),(x-1,y),(x,y+1),(x,y-1) is valid or not and if valid then check that value at that coordinate should be equal to precolor and value of that coordinate in vis[][] is 0.
- If all the above condition is true push the corresponding coordinate in queue and mark as 1 in vis[][]
- Print the matrix.
Below is the implementation of the above approach:
C++
// CPP program for above approach #include <bits/stdc++.h> using namespace std; // Function to check valid coordinate int validCoord( int x, int y, int n, int m) { if (x < 0 || y < 0) { return 0; } if (x >= n || y >= m) { return 0; } return 1; } // Function to run bfs void bfs( int n, int m, int data[][8], int x, int y, int color) { // Visiing array int vis[101][101]; // Initialing all as zero memset (vis, 0, sizeof (vis)); // Creating queue for bfs queue<pair< int , int > > obj; // Pushing pair of {x, y} obj.push({ x, y }); // Marking {x, y} as visited vis[x][y] = 1; // Untill queue is emppty while (obj.empty() != 1) { // Extrating front pair pair< int , int > coord = obj.front(); int x = coord.first; int y = coord.second; int preColor = data[x][y]; data[x][y] = color; // Poping front pair of queue obj.pop(); // For Upside Pixel or Cell if (validCoord(x + 1, y, n, m) && vis[x + 1][y] == 0 && data[x + 1][y] == preColor) { obj.push({ x + 1, y }); vis[x + 1][y] = 1; } // For Downside Pixel or Cell if (validCoord(x - 1, y, n, m) && vis[x - 1][y] == 0 && data[x - 1][y] == preColor) { obj.push({ x - 1, y }); vis[x - 1][y] = 1; } // For Right side Pixel or Cell if (validCoord(x, y + 1, n, m) && vis[x][y + 1] == 0 && data[x][y + 1] == preColor) { obj.push({ x, y + 1 }); vis[x][y + 1] = 1; } // For Left side Pixel or Cell if (validCoord(x, y - 1, n, m) && vis[x][y - 1] == 0 && data[x][y - 1] == preColor) { obj.push({ x, y - 1 }); vis[x][y - 1] = 1; } } // Printing The Changed Matrix Of Pixels for ( int i = 0; i < n; i++) { for ( int j = 0; j < m; j++) { cout << data[i][j] << " " ; } cout << endl; } cout << endl; } // Driver Code int main() { int n, m, x, y, color; n = 8; m = 8; int data[8][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 }, }; x = 4, y = 4, color = 3; // Function Call bfs(n, m, data, x, y, color); return 0; } |
Java
/*package whatever //do not write package name here */ import java.io.*; import java.util.*; // Class to store the pairs class Pair implements Comparable<Pair> { int first; int second; public Pair( int first, int second) { this .first = first; this .second = second; } @Override public int compareTo(Pair o) { return second - o.second; } } class GFG { public static int validCoord( int x, int y, int n, int m) { if (x < 0 || y < 0 ) { return 0 ; } if (x >= n || y >= m) { return 0 ; } return 1 ; } // Function to run bfs public static void bfs( int n, int m, int data[][], int x, int y, int color) { // Visiing array int vis[][]= new int [ 101 ][ 101 ]; // Initialing all as zero for ( int i= 0 ;i<= 100 ;i++){ for ( int j= 0 ;j<= 100 ;j++){ vis[i][j]= 0 ; } } // Creating queue for bfs Queue<Pair> obj = new LinkedList<>(); // Pushing pair of {x, y} Pair pq= new Pair(x,y); obj.add(pq); // Marking {x, y} as visited vis[x][y] = 1 ; // Untill queue is emppty while (!obj.isEmpty()) { // Extrating front pair Pair coord = obj.peek(); int x1 = coord.first; int y1 = coord.second; int preColor = data[x1][y1]; data[x1][y1] = color; // Poping front pair of queue obj.remove(); // For Upside Pixel or Cell if ((validCoord(x1 + 1 , y1, n, m)== 1 ) && vis[x1 + 1 ][y1] == 0 && data[x1 + 1 ][y1] == preColor) { Pair p= new Pair(x1 + 1 , y1); obj.add(p); vis[x1 + 1 ][y1] = 1 ; } // For Downside Pixel or Cell if ((validCoord(x1 - 1 , y1, n, m)== 1 ) && vis[x1 - 1 ][y1] == 0 && data[x1 - 1 ][y1] == preColor) { Pair p= new Pair(x1- 1 ,y1); obj.add(p); vis[x1- 1 ][y1] = 1 ; } // For Right side Pixel or Cell if ((validCoord(x1, y1 + 1 , n, m)== 1 ) && vis[x1][y1 + 1 ] == 0 && data[x1][y1 + 1 ] == preColor) { Pair p= new Pair(x1,y1 + 1 ); obj.add(p); vis[x1][y1 + 1 ] = 1 ; } // For Left side Pixel or Cell if ((validCoord(x1, y1 - 1 , n, m)== 1 ) && vis[x1][y1 - 1 ] == 0 && data[x1][y1 - 1 ] == preColor) { Pair p= new Pair(x1,y1 - 1 ); obj.add(p); vis[x1][y1 - 1 ] = 1 ; } } // Printing The Changed Matrix Of Pixels for ( int i = 0 ; i < n; i++) { for ( int j = 0 ; j < m; j++) { System.out.print(data[i][j]+ " " ); } System.out.println(); } System.out.println(); } public static void main (String[] args) { int nn, mm, xx, yy, colorr; nn = 8 ; mm = 8 ; int dataa[][] = {{ 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 },}; xx = 4 ; yy = 4 ; colorr = 3 ; // Function Call bfs(nn, mm, dataa, xx, yy, colorr); } } // This code is contributed by Manu Pathria |
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
References:
http://en.wikipedia.org/wiki/Flood_fill
This article is contributed by Anmol. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.