-
Notifications
You must be signed in to change notification settings - Fork 20.5k
Feature iterative flood fill #6584
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
DenizAltunkapan
merged 10 commits into
TheAlgorithms:master
from
CrodiYa:feature-iterative-flood-fill
Oct 9, 2025
Merged
Changes from 8 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
9a38e8b
feat: FloodFill Algorithm with iterative approach
CrodiYa 1e14bec
feat: tests for IterativeFloodFill
CrodiYa d69bf20
docs: add link to floodFill algorithm
CrodiYa c3f43d8
codeStyle fix
CrodiYa fda0d6e
tests: add tests for edge cases
CrodiYa 4b5dfb2
codeStyle fix
CrodiYa 0cf68b7
codeStyle fix
CrodiYa 5c52b36
codeStyle fix
CrodiYa d806c35
refactor: reorganize structure and add JavaDoc
CrodiYa 83ac241
Merge branch 'master' into feature-iterative-flood-fill
DenizAltunkapan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
81 changes: 81 additions & 0 deletions
81
src/main/java/com/thealgorithms/others/IterativeFloodFill.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package com.thealgorithms.others; | ||
|
||
import java.util.LinkedList; | ||
import java.util.Queue; | ||
|
||
public final class IterativeFloodFill { | ||
private IterativeFloodFill() { | ||
} | ||
|
||
/** | ||
* Represents a point in 2D space with integer coordinates. | ||
*/ | ||
private static class Point { | ||
final int x; | ||
final int y; | ||
|
||
Point(final int x, final int y) { | ||
this.x = x; | ||
this.y = y; | ||
} | ||
} | ||
|
||
/** | ||
* Checks if a pixel should be skipped during flood fill operation. | ||
* | ||
* @param image The image to get boundaries | ||
* @param x The x co-ordinate of pixel to check | ||
* @param y The y co-ordinate of pixel to check | ||
* @param oldColor The old color which is to be replaced in the image | ||
* @return {@code true} if pixel should be skipped, else {@code false} | ||
*/ | ||
private static boolean shouldSkipPixel(final int[][] image, final int x, final int y, final int oldColor) { | ||
|
||
if (x < 0 || x >= image.length || y < 0 || y >= image[0].length || image[x][y] != oldColor) { | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* Iteratively fill the 2D image with new color | ||
* | ||
* @param image The image to be filled | ||
* @param x The x co-ordinate at which color is to be filled | ||
* @param y The y co-ordinate at which color is to be filled | ||
* @param newColor The new color which to be filled in the image | ||
* @param oldColor The old color which is to be replaced in the image | ||
* @see <a href=https://www.geeksforgeeks.org/dsa/flood-fill-algorithm>FloodFill BFS<a/> | ||
*/ | ||
public static void floodFill(final int[][] image, final int x, final int y, final int newColor, final int oldColor) { | ||
if (image.length == 0 || image[0].length == 0 || newColor == oldColor || shouldSkipPixel(image, x, y, oldColor)) { | ||
return; | ||
} | ||
|
||
Queue<Point> queue = new LinkedList<>(); | ||
queue.add(new Point(x, y)); | ||
|
||
int[] dx = {0, 0, -1, 1, 1, -1, 1, -1}; | ||
int[] dy = {-1, 1, 0, 0, -1, 1, 1, -1}; | ||
|
||
while (!queue.isEmpty()) { | ||
Point currPoint = queue.poll(); | ||
|
||
if (shouldSkipPixel(image, currPoint.x, currPoint.y, oldColor)) { | ||
continue; | ||
} | ||
|
||
image[currPoint.x][currPoint.y] = newColor; | ||
|
||
for (int i = 0; i < 8; i++) { | ||
int curX = currPoint.x + dx[i]; | ||
int curY = currPoint.y + dy[i]; | ||
|
||
if (!shouldSkipPixel(image, curX, curY, oldColor)) { | ||
queue.add(new Point(curX, curY)); | ||
} | ||
} | ||
} | ||
} | ||
} |
163 changes: 163 additions & 0 deletions
163
src/test/java/com/thealgorithms/others/IterativeFloodFillTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
package com.thealgorithms.others; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertArrayEquals; | ||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
class IterativeFloodFillTest { | ||
|
||
@Test | ||
void testForEmptyImage() { | ||
int[][] image = {}; | ||
int[][] expected = {}; | ||
|
||
IterativeFloodFill.floodFill(image, 4, 5, 3, 2); | ||
assertArrayEquals(expected, image); | ||
} | ||
|
||
@Test | ||
void testForSingleElementImage() { | ||
int[][] image = {{1}}; | ||
int[][] expected = {{3}}; | ||
|
||
IterativeFloodFill.floodFill(image, 0, 0, 3, 1); | ||
assertArrayEquals(expected, image); | ||
} | ||
|
||
@Test | ||
void testForEmptyRow() { | ||
int[][] image = {{}}; | ||
int[][] expected = {{}}; | ||
|
||
IterativeFloodFill.floodFill(image, 4, 5, 3, 2); | ||
assertArrayEquals(expected, image); | ||
} | ||
|
||
@Test | ||
void testForImageOne() { | ||
int[][] image = { | ||
{0, 0, 0, 0, 0, 0, 0}, | ||
{0, 3, 3, 3, 3, 0, 0}, | ||
{0, 3, 1, 1, 5, 0, 0}, | ||
{0, 3, 1, 1, 5, 5, 3}, | ||
{0, 3, 5, 5, 1, 1, 3}, | ||
{0, 0, 0, 5, 1, 1, 3}, | ||
{0, 0, 0, 3, 3, 3, 3}, | ||
}; | ||
|
||
int[][] expected = { | ||
{0, 0, 0, 0, 0, 0, 0}, | ||
{0, 3, 3, 3, 3, 0, 0}, | ||
{0, 3, 2, 2, 5, 0, 0}, | ||
{0, 3, 2, 2, 5, 5, 3}, | ||
{0, 3, 5, 5, 2, 2, 3}, | ||
{0, 0, 0, 5, 2, 2, 3}, | ||
{0, 0, 0, 3, 3, 3, 3}, | ||
}; | ||
|
||
IterativeFloodFill.floodFill(image, 2, 2, 2, 1); | ||
assertArrayEquals(expected, image); | ||
} | ||
|
||
@Test | ||
void testForImageTwo() { | ||
int[][] image = { | ||
{0, 0, 1, 1, 0, 0, 0}, | ||
{1, 1, 3, 3, 3, 0, 0}, | ||
{1, 3, 1, 1, 5, 0, 0}, | ||
{0, 3, 1, 1, 5, 5, 3}, | ||
{0, 3, 5, 5, 1, 1, 3}, | ||
{0, 0, 0, 5, 1, 1, 3}, | ||
{0, 0, 0, 1, 3, 1, 3}, | ||
}; | ||
|
||
int[][] expected = { | ||
{0, 0, 2, 2, 0, 0, 0}, | ||
{2, 2, 3, 3, 3, 0, 0}, | ||
{2, 3, 2, 2, 5, 0, 0}, | ||
{0, 3, 2, 2, 5, 5, 3}, | ||
{0, 3, 5, 5, 2, 2, 3}, | ||
{0, 0, 0, 5, 2, 2, 3}, | ||
{0, 0, 0, 2, 3, 2, 3}, | ||
}; | ||
|
||
IterativeFloodFill.floodFill(image, 2, 2, 2, 1); | ||
assertArrayEquals(expected, image); | ||
} | ||
|
||
@Test | ||
void testForImageThree() { | ||
int[][] image = { | ||
{1, 1, 2, 3, 1, 1, 1}, | ||
{1, 0, 0, 1, 0, 0, 1}, | ||
{1, 1, 1, 0, 3, 1, 2}, | ||
}; | ||
|
||
int[][] expected = { | ||
{4, 4, 2, 3, 4, 4, 4}, | ||
{4, 0, 0, 4, 0, 0, 4}, | ||
{4, 4, 4, 0, 3, 4, 2}, | ||
}; | ||
|
||
IterativeFloodFill.floodFill(image, 0, 1, 4, 1); | ||
assertArrayEquals(expected, image); | ||
} | ||
|
||
@Test | ||
void testForSameNewAndOldColor() { | ||
int[][] image = {{1, 1, 2}, {1, 0, 0}, {1, 1, 1}}; | ||
|
||
int[][] expected = {{1, 1, 2}, {1, 0, 0}, {1, 1, 1}}; | ||
|
||
IterativeFloodFill.floodFill(image, 0, 1, 1, 1); | ||
assertArrayEquals(expected, image); | ||
} | ||
|
||
@Test | ||
void testForBigImage() { | ||
int[][] image = new int[100][100]; | ||
|
||
assertDoesNotThrow(() -> IterativeFloodFill.floodFill(image, 0, 0, 1, 0)); | ||
} | ||
|
||
@Test | ||
void testForBelowZeroX() { | ||
int[][] image = {{1, 1, 2}, {1, 0, 0}, {1, 1, 1}}; | ||
|
||
int[][] expected = {{1, 1, 2}, {1, 0, 0}, {1, 1, 1}}; | ||
|
||
IterativeFloodFill.floodFill(image, -1, 1, 1, 0); | ||
assertArrayEquals(expected, image); | ||
} | ||
|
||
@Test | ||
void testForBelowZeroY() { | ||
int[][] image = {{1, 1, 2}, {1, 0, 0}, {1, 1, 1}}; | ||
|
||
int[][] expected = {{1, 1, 2}, {1, 0, 0}, {1, 1, 1}}; | ||
|
||
IterativeFloodFill.floodFill(image, 1, -1, 1, 0); | ||
assertArrayEquals(expected, image); | ||
} | ||
|
||
@Test | ||
void testForAboveBoundaryX() { | ||
int[][] image = {{1, 1, 2}, {1, 0, 0}, {1, 1, 1}}; | ||
|
||
int[][] expected = {{1, 1, 2}, {1, 0, 0}, {1, 1, 1}}; | ||
|
||
IterativeFloodFill.floodFill(image, 100, 1, 1, 0); | ||
assertArrayEquals(expected, image); | ||
} | ||
|
||
@Test | ||
void testForAboveBoundaryY() { | ||
int[][] image = {{1, 1, 2}, {1, 0, 0}, {1, 1, 1}}; | ||
|
||
int[][] expected = {{1, 1, 2}, {1, 0, 0}, {1, 1, 1}}; | ||
|
||
IterativeFloodFill.floodFill(image, 1, 100, 1, 0); | ||
assertArrayEquals(expected, image); | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.