二维数组搜索FloodFill算法
Posted 白小白2020
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二维数组搜索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算法的主要内容,如果未能解决你的问题,请参考以下文章
剑指offer(C++)-JZ4:二维数组中的查找(算法-搜索算法)