2020-06-22 01:45:24 +00:00
|
|
|
|
---
|
|
|
|
|
id: ff
|
|
|
|
|
title: Flood Fill
|
2020-07-03 23:48:03 +00:00
|
|
|
|
author: Darren Yao
|
2020-06-22 01:45:24 +00:00
|
|
|
|
prerequisites:
|
2020-06-22 20:51:12 +00:00
|
|
|
|
- Silver - Depth First Search
|
2020-06-29 20:20:17 +00:00
|
|
|
|
description: "Flood Fill refers to finding connected components in a graph that is respresented by a grid."
|
2020-06-26 18:00:32 +00:00
|
|
|
|
frequency: 3
|
2020-06-22 01:45:24 +00:00
|
|
|
|
---
|
|
|
|
|
|
2020-06-24 23:33:36 +00:00
|
|
|
|
import { Problem } from "../models";
|
|
|
|
|
|
|
|
|
|
export const metadata = {
|
|
|
|
|
problems: {
|
|
|
|
|
sample: [
|
2020-07-03 23:48:03 +00:00
|
|
|
|
new Problem("LC", "Flood Fill", "https://leetcode.com/problems/flood-fill/", "Intro|Easy", false, []),
|
2020-06-24 23:33:36 +00:00
|
|
|
|
new Problem("CSES", "Counting Rooms", "1192", "Easy", false, []),
|
|
|
|
|
],
|
|
|
|
|
general: [
|
|
|
|
|
new Problem("CSES", "Labyrinth", "1193", "Easy", false, []),
|
2020-06-25 01:38:05 +00:00
|
|
|
|
new Problem("Silver", "Count Cross", "716", "Easy", false, ["FF"]),
|
2020-06-24 23:33:36 +00:00
|
|
|
|
new Problem("Silver", "Ice Perimeter", "895", "Easy", false, []),
|
|
|
|
|
new Problem("Silver", "Switching on the Lights", "570", "Normal", false, []),
|
|
|
|
|
new Problem("Silver", "Build Gates", "596", "Normal", false, []),
|
|
|
|
|
new Problem("Silver", "Milk Pails", "620", "Normal", false, []),
|
|
|
|
|
new Problem("Silver", "Where's Bessie?", "740", "Normal", false, []),
|
|
|
|
|
new Problem("Silver", "Why Did the Cow Cross the Road III", "716", "Normal", false, []),
|
|
|
|
|
new Problem("Silver", "Multiplayer Moo", "836", "Hard", false, []),
|
|
|
|
|
new Problem("Silver", "Snow Boots", "811", "Hard", false, []),
|
|
|
|
|
new Problem("Silver", "Mooyo Mooyo", "860", "Hard", false, []),
|
|
|
|
|
],
|
|
|
|
|
}
|
|
|
|
|
};
|
2020-06-22 01:45:24 +00:00
|
|
|
|
|
2020-06-24 23:33:36 +00:00
|
|
|
|
<problems-list problems={metadata.problems.sample} />
|
|
|
|
|
|
2020-06-29 20:20:17 +00:00
|
|
|
|
## Lesson
|
2020-06-22 01:45:24 +00:00
|
|
|
|
|
2020-07-03 23:48:03 +00:00
|
|
|
|
|
|
|
|
|
Floodfill is an algorithm that identifies and labels the connected component that a
|
|
|
|
|
particular cell belongs to, in a multi-dimensional array. Essentially, it’s DFS, but on a grid,
|
|
|
|
|
and we want to find the connected component of all the connected cells with the same number.
|
|
|
|
|
For example, let’s look at the following grid and see how floodfill works, starting from the
|
|
|
|
|
top-left cell. The color scheme will be the same: red for the node currently being processed,
|
|
|
|
|
blue for nodes already visited, and uncolored for nodes not yet visited.
|
|
|
|
|
|
|
|
|
|
(tables)
|
|
|
|
|
|
|
|
|
|
As opposed to an explicit graph where the edges are given, a grid is an implicit graph.
|
|
|
|
|
This means that the neighbors are just the nodes directly adjacent in the four cardinal
|
|
|
|
|
directions.
|
|
|
|
|
|
|
|
|
|
Usually, grids given in problems will be $N$ by $M$, so the first line of the input contains the
|
|
|
|
|
numbers $N$ and $M$. In this example, we will use an two-dimensional integer array to store the
|
|
|
|
|
grid, but depending on the problem, a two-dimensional character array or a two-dimensional
|
|
|
|
|
boolean array may be more appropriate. Then, there are $N$ rows, each with $M$ numbers
|
|
|
|
|
containing the contents of each square in the grid. Example input might look like the following
|
|
|
|
|
(varies between problems):
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
3 4
|
|
|
|
|
1 1 2 1
|
|
|
|
|
2 3 2 1
|
|
|
|
|
1 3 3 3
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
And we’ll want to input the grid as follows:
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
static int[][] grid;
|
|
|
|
|
static int n, m;
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args){
|
|
|
|
|
int n = r.nextInt();
|
|
|
|
|
int m = r.nextInt();
|
|
|
|
|
grid = new int[n][m];
|
|
|
|
|
for(int i = 0; i < n; i++){
|
|
|
|
|
for(int j = 0; j < m; j++){
|
|
|
|
|
grid[i][j] = r.nextInt();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int grid[MAXN][MAXM];
|
|
|
|
|
int n, m;
|
|
|
|
|
|
|
|
|
|
int main(){
|
|
|
|
|
cin >> n >> m;
|
|
|
|
|
for(int i = 0; i < n; i++){
|
|
|
|
|
for(int j = 0; j < m; j++){
|
|
|
|
|
cin >> grid[i][j];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Implementation
|
|
|
|
|
|
2020-06-28 16:03:46 +00:00
|
|
|
|
<resources>
|
2020-07-03 23:48:03 +00:00
|
|
|
|
<resource source="GFG" title="Flood Fill" url="flood-fill-algorithm-implement-fill-paint"></resource>
|
2020-06-28 16:03:46 +00:00
|
|
|
|
</resources>
|
2020-06-22 01:45:24 +00:00
|
|
|
|
|
2020-07-03 23:48:03 +00:00
|
|
|
|
When doing floodfill, we will maintain an $N\times M$ array of booleans to keep track of
|
|
|
|
|
which squares have been visited, and a global variable to maintain the size of the current
|
|
|
|
|
component we are visiting. Make sure to store the grid, the visited array, dimensions, and
|
|
|
|
|
the current size variable globally.
|
|
|
|
|
|
|
|
|
|
This means that we want to recursively call the search function from the squares above,
|
|
|
|
|
below, and to the left and right of our current square. The algorithm to find the size of a
|
|
|
|
|
connected component in a grid using floodfill is as follows (we’ll also maintain a 2D visited array).
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
static int[][] grid; // the grid itself
|
|
|
|
|
static int n, m; // grid dimensions, rows and columns
|
|
|
|
|
static boolean[][] visited; // keeps track of which nodes have been visited
|
|
|
|
|
static int currentSize = 0; // reset to 0 each time we start a new component
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args){
|
|
|
|
|
/**
|
|
|
|
|
* input code and other problem-specific stuff here
|
|
|
|
|
*/
|
|
|
|
|
for(int i = 0; i < n; i++){
|
|
|
|
|
for(int j = 0; j < m; j++){
|
|
|
|
|
if(!visited[i][j]){
|
|
|
|
|
currentSize = 0;
|
|
|
|
|
floodfill(i, j, grid[i][j]);
|
|
|
|
|
// start a floodfill if the square hasn't already been visited,
|
|
|
|
|
// and then store or otherwise use the component size
|
|
|
|
|
// for whatever it's needed for
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void floodfill(int r, int c, int color){
|
|
|
|
|
if(r < 0 || r >= n || c < 0 || c >= m) return; // if outside grid
|
|
|
|
|
if(grid[r][c] != color) return; // wrong color
|
|
|
|
|
if(visited[r][c]) return; // already visited this square
|
|
|
|
|
visited[r][c] = true; // mark current square as visited
|
|
|
|
|
currentSize++; // increment the size for each square we visit
|
|
|
|
|
// recursively call floodfill for neighboring squares
|
|
|
|
|
floodfill(r, c+1, color);
|
|
|
|
|
floodfill(r, c-1, color);
|
|
|
|
|
floodfill(r-1, c, color);
|
|
|
|
|
floodfill(r+1, c, color);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int grid[MAXN][MAXM]; // the grid itself
|
|
|
|
|
int n, m; // grid dimensions, rows and columns
|
|
|
|
|
bool visited[MAXN][MAXM]; // keeps track of which nodes have been visited
|
|
|
|
|
int currentSize = 0; // reset to 0 each time we start a new component
|
|
|
|
|
|
|
|
|
|
void floodfill(int r, int c, int color){
|
|
|
|
|
if(r < 0 || r >= n || c < 0 || c >= m) return; // if outside grid
|
|
|
|
|
if(grid[r][c] != color) return; // wrong color
|
|
|
|
|
if(visited[r][c]) return; // already visited this square
|
|
|
|
|
visited[r][c] = true; // mark current square as visited
|
|
|
|
|
currentSize++; // increment the size for each square we visit
|
|
|
|
|
// recursively call floodfill for neighboring squares
|
|
|
|
|
floodfill(r, c+1, color);
|
|
|
|
|
floodfill(r, c-1, color);
|
|
|
|
|
floodfill(r-1, c, color);
|
|
|
|
|
floodfill(r+1, c, color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(){
|
|
|
|
|
/**
|
|
|
|
|
* input code and other problem-specific stuff here
|
|
|
|
|
*/
|
|
|
|
|
for(int i = 0; i < n; i++){
|
|
|
|
|
for(int j = 0; j < m; j++){
|
|
|
|
|
if(!visited[i][j]){
|
|
|
|
|
currentSize = 0;
|
|
|
|
|
floodfill(i, j, grid[i][j]);
|
|
|
|
|
// start a floodfill if the square hasn't
|
|
|
|
|
// already been visited, and then
|
|
|
|
|
// store or otherwise use the component size for whatever
|
|
|
|
|
// it's needed for
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2020-06-24 23:33:36 +00:00
|
|
|
|
## Problems
|
|
|
|
|
|
|
|
|
|
<problems-list problems={metadata.problems.general} />
|