题目描述
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例 1:
输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCCED”
输出:true
示例 2:
输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “SEE”
输出:true
示例 3:
输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCB”
输出:false
提示:
- m == board.length
- n = board[i].length
- 1 <= m, n <= 6
- 1 <= word.length <= 15
- board 和 word 仅由大小写英文字母组成
解法
我们可以枚举网格的每一个位置 (i,j) 作为搜索的起点,然后从起点开始进行深度优先搜索,如果可以搜索到单词的末尾,就说明单词存在,否则说明单词不存在。
因此,我们设计一个函数 dfs(i,j,k),表示从网格的 (i,j) 位置出发,且从单词的第 k 个字符开始搜索,是否能够搜索成功。函数 dfs(i,j,k) 的执行步骤如下:
- 如果 k=∣word∣−1,说明已经搜索到单词的最后一个字符,此时只需要判断网格 (i,j) 位置的字符是否等于
word[k],如果相等则说明单词存在,否则说明单词不存在。无论单词是否存在,都无需继续往下搜索,因此直接返回结果。 - 否则,如果 word[k] 字符不等于网格 (i,j) 位置的字符,说明本次搜索失败,直接返回 false。
- 否则,我们将网格 (i,j) 位置的字符暂存于 c 中,然后将此位置的字符修改为一个特殊字符
‘0’,代表此位置的字符已经被使用过,防止之后搜索时重复使用。然后我们从 (i,j) 位置的上、下、左、右四个方向分别出发,去搜索网格中第 k+1 个字符,如果四个方向有任何一个方向搜索成功,就说明搜索成功,否则说明搜索失败,此时我们需要还原网格 (i,j) 位置的字符,即把 c 放回网格 (i,j) 位置(回溯)。
在主函数中,我们枚举网格中的每一个位置 (i,j) 作为起点,如果调用 dfs(i,j,0) 返回 true,就说明单词存在,否则说明单词不存在,返回 false。
时间复杂度 O(m×n×3k ),空间复杂度 O(min(m×n,k))。其中 m 和 n 分别是网格的行数和列数;而 k 是字符串 word 的长度。
class Solution(object):
def exist(self, board, word):
"""
:type board: List[List[str]]
:type word: str
:rtype: bool
"""
for i in range(len(board)):
for j in range(len(board[0])):
if self.helper(board,i,j,word,0):
return True
return False
def helper(self,board,i,j,word,index):
if index == len(word):
return True
if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or board[i][j] != word[index]:
return False
board[i][j] = "*"
found = self.helper(board,i+1,j,word,index+1)\
or self.helper(board,i,j+1,word,index+1)\
or self.helper(board,i-1,j,word,index+1)\
or self.helper(board,i,j-1,word,index+1)
board[i][j] = word[index]
return found