如何基于现有flood fill算法获取填充区域的边界相邻值
问题描述
我正在开发用于获取flood fill相邻边界值的算法,现有如下二维数组:
我需要对图中黄色标注的flood fill边界对应值进行求和,目前已实现基础flood fill功能作为开发起点,请问有什么方案可以获取所需的边界值?以下是我当前的实现代码:
// Java program to implement flood fill algorithm class GFG { // Dimensions 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]; if(prevC==newC) return; 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, 2, 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(); } } }
可行实现方案
下面提供两种常用实现思路,可根据使用场景选择:
方案1:填充过程中实时收集边界(性能最优)
无需二次遍历全数组,仅在flood fill递归过程中完成边界统计,适合大尺寸二维数组场景。
修改逻辑如下:
- 新增边界和存储变量,以及边界访问标记数组,避免同一个边界值被重复累加
- 递归判断时,如果相邻单元格不属于原始填充色
prevC且坐标合法,同时未被标记为已统计,就将其值计入总和并做标记
修改后的核心代码示例:
class GFG { static int M = 8; static int N = 8; static int boundarySum = 0; static boolean[][] visitedBoundary = new boolean[M][N]; // 标记已统计的边界,避免重复计算 static void floodFillUtil(int screen[][], int x, int y, int prevC, int newC) { if (x < 0 || x >= M || y < 0 || y >= N) return; if (screen[x][y] != prevC){ // 坐标合法且未统计过的边界值计入总和 if (x >=0 && x < M && y >=0 && y < N && !visitedBoundary[x][y]) { boundarySum += screen[x][y]; visitedBoundary[x][y] = true; } return; } screen[x][y] = newC; 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); } // 其余原有逻辑不变,调用完成后直接取boundarySum即可得到边界总和 }
方案2:填充完成后二次遍历统计(实现最简单)
不需要修改原有flood fill的核心逻辑,填充完成后遍历全数组统计边界值,适合小尺寸数组快速实现。
统计逻辑如下:
遍历数组每个单元格,如果当前单元格是填充后的颜色newC,就检查它的上下左右四个相邻单元格,只要相邻单元格不是newC且坐标合法,同时未被统计过,就将其值加入总和。
代码示例:
// 原有floodFill调用完成后执行以下逻辑 static int calculateBoundarySum(int[][] screen, int newC) { int sum = 0; boolean[][] visited = new boolean[M][N]; // 四个方向的偏移量 int[][] dirs = {{-1,0},{1,0},{0,-1},{0,1}}; for (int i = 0; i < M; i++) { for (int j = 0; j < N; j++) { if (screen[i][j] == newC) { for (int[] dir : dirs) { int nx = i + dir[0]; int ny = j + dir[1]; if (nx >=0 && nx < M && ny >=0 && ny < N && screen[nx][ny] != newC && !visited[nx][ny]) { sum += screen[nx][ny]; visited[nx][ny] = true; } } } } } return sum; }
内容的提问来源于stack exchange,提问作者Katia
相关产品推荐
相关产品推荐

