> Problem: [79. 单词搜索](https://leetcode.cn/problems/word-search/description/)
# 思路
> 第一次写Flood Fill(泛洪填充)问题时间用了比较久才搞懂这个矩阵填充的模板。回溯问题上首先接触的切割问题,然后从切割问题总结的模板到组合问题,最后在这个Flood Fill问题。看到问题一脸懵,尝试用组合模板来解决,后来发现不行,想了想要在矩阵的特定节点做上下左右的移动,于是想到了加减坐标来移动,移动的情况一下再对字符串word做对比。
# 解题方法
> 还是回溯三部曲:
1、首先确定递归出口,这道题的递归出口需要判断bool值于是需要两个递归出口,第一个是边界条件检查||是否越界||是否访问||是否等于预期值。第二个条件是否等于len(word),如果等于的话直接出口。
m, n := len(board), len(board[0])
if i < 0 || j < 0 || i >= m || j >= n || visited[i][j] || board[i][j] != word[k] {
return false
}
if k == len(word)-1 {
return true
}
>这儿遇到一个坑,当 i >= len(board) 或 j >= len(board[0]) 为 true 时,访问 visited[i][j] 或 board[i][j] 就会导致越界。找错误找了半天。
2、单层逻辑实现,这个逻辑实现就是判断是不是等于word匹配字符就好了
3、回溯就好,这儿的回溯用了defer保证每个visited都会被重置成flase
# 复杂度
- 时间复杂度:
> 回溯就不谈复杂度了
func exist(board [][]byte, word string) bool {
if len(board) == 0 || len(board[0]) == 0 {
return false
}
m, n := len(board), len(board[0])
visited := make([][]bool, m)
for i := 0; i < m; i++ {
visited[i] = make([]bool, n)
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if backTracking(board,visited,i,j,0,word){
return true
}
}
}
return false
}
func backTracking(board [][]byte, visited [][]bool, i, j, k int, word string) bool {
m, n := len(board), len(board[0])
if i < 0 || j < 0 || i >= m || j >= n || visited[i][j] || board[i][j] != word[k] {
return false
}
if k == len(word)-1 {
return true
}
visited[i][j] = true
defer func() {
visited[i][j] = false
}()
if backTracking(board, visited, i-1, j, k+1, word) ||backTracking(board, visited, i+1, j, k+1, word)|| backTracking(board, visited, i, j-1, k+1, word)||backTracking(board, visited, i, j+1, k+1, word){
return true
}
return false
}