二维数组搜索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
}
上一篇:单词拆分


下一篇:LeetCode 139. 单词拆分