题面
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
- 给定 word = “ABCCED”, 返回 true
- 给定 word = “SEE”, 返回 true
- 给定 word = “ABCB”, 返回 false
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-search
思路
- 每个board坐标点信息为搜索起点,以此对应单词进行同步深度递归
- 将board 视为一个带有坐标信息的集合,每个位置代表一个坐标
- board[i][j] 可能的方向有上,下,左,右, 即每个点有四种分支状态
- 在顺序扫描board,在当前点所有状态比较完毕后,放一个标识,进行下一个点位尝试,碰到已访问过回溯,换而言之已访问过不再访问
- 用数组坐标组合值形式决定方向,board行列之积视为可能的最大标识数,四个方向尝试返回有一为真值,立刻返回,同理board扫描查找
代码
func exist(board [][]byte, word string) bool {
rows,cols := len(board),len(board[0])
posX,posY := []int{0,0,1,-1},[]int{1,-1,0,0}
vis := make([]bool,rows*cols)
var search func(int,int,int)bool
search = func(i, j, idx int) bool {
if board[i][j] != word[idx] {
return false
}else if idx+1 == len(word) { // 隐式带字符相等的条件比较
return true
}
vis[i*cols+j] = true // 标记被访问过的节点
for k:=0;k<4;k++ { // 上下左右四个可选分支
x,y := i+ posX[k],j + posY[k] // 确保下一个坐标合法,未被使用,进行下轮比较
if x>=0 && x < rows && y >= 0 && y < cols && !vis[x*cols + y] && search(x,y,idx+1) {
return true
}
}
vis[i*cols+j] = false
return false
}
// board每个索引位作为深度递归搜索起点 与单词从首位进行比较
for i:=0;i<rows;i++ {
for j:=0;j<cols;j++ {
if search(i,j, 0){
return true
}
}
}
return false
}