Java教程

二维数组搜索FloodFill算法

本文主要是介绍二维数组搜索FloodFill算法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1.具体问题

二维数组的搜索问题,二维数组可以看成四叉树进行搜索。

  • 图像渲染
  • 自动魔棒功能
  • 扫雷

2.图像渲染问题

有一幅以二维整数数组表示的图画,每一个整数表示该图画的像素值大小,数值在 $0$$65535$ 之间。

给你一个坐标$(sr, sc)$表示图像渲染开始的像素值(行 ,列)和一个新的颜色值$newColor$,让你重新上色这幅图像。

为了完成上色工作,从初始坐标开始,记录初始坐标的上下左右四个方向上像素值与初始坐标相同的相连像素点,接着再记录这四个方向上符合条件的像素点与他们对应四个方向上像素值与初始坐标相同的相连像素点,……,重复该过程。将所有有记录的像素点的颜色值改为新的颜色值。

最后返回经过上色渲染后的图像。

2.1 深度优先搜索

func floodFill(image [][]int, sr int, sc int, newColor int) [][]int {
	startColor := image[sr][sc]
	var dfs func(int, int)
	dfs = func(i, j int) {
		if i < 0 || j < 0 || i >= len(image) || j >= len(image[0]) {
			return
		}
		if image[i][j] != startColor {
			return
		}
		if image[i][j] == -1 { // 已经访问过了
			return
		}
		image[i][j] = -1 // 标记已经访问过了 防止原始颜色和新颜色一个值时 递归出不来
		dfs(i-1, j)
		dfs(i+1, j)
		dfs(i, j-1)
		dfs(i, j+1)
		image[i][j] = newColor
	}
	dfs(sr, sc)
	return image
}

注意细节:如果起始颜色与新颜色同色时,会重复访问以前访问过的位置,这时访问过的位置要加标志才可以,这里利用回溯进行标记,很巧妙。

2.2 广度优先搜索

发散状搜索

type pos struct {
	i int
	j int
}

// 广度优先搜索
func floodFill(image [][]int, sr int, sc int, newColor int) [][]int {
	startColor := image[sr][sc]
	offset := [][]int{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}
	visted := make([][]bool, len(image))
	for i := 0; i < len(visted); i++ {
		visted[i] = make([]bool, len(image[0]))
	}
	queue := []pos{}
	queue = append(queue, pos{sr, sc})
	for len(queue) != 0 {
		cur := queue[0] // 出队
		queue = queue[1:]
		if cur.i < 0 || cur.j < 0 || cur.i >= len(image) || cur.j >= len(image[0]) {
			continue
		}
		if image[cur.i][cur.j] != startColor {
			continue
		}
		if visted[cur.i][cur.j] {
			continue
		}
		image[cur.i][cur.j] = newColor
		visted[cur.i][cur.j] = true
		for k := 0; k < len(offset); k++ {
			queue = append(queue, pos{cur.i + offset[k][0], cur.j + offset[k][1]}) // 入队
		}
	}
	return image
}
这篇关于二维数组搜索FloodFill算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!