题目
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]
给定 word = “ABCCED”, 返回 true
给定 word = “SEE”, 返回 true
给定 word = “ABCB”, 返回 false
自练代码(一旦错了,无法回溯。。。)
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
hang = len(board)
lie = len(board[0])
index = 0
for i in range(hang):
for j in range(lie):
if board[i][j] == word[index]:
path = [(i,j)]
ii, jj = i, j
now = index
ok = 1
if ok and now == len(word)-1:
return(True)
while(ok and now < len(word)):
now += 1
if ii+1<hang and board[ii+1][jj] == word[now] and (ii+1,jj) not in path:
ii = ii + 1
path.append((ii, jj))
elif ii-1>-1 and board[ii-1][jj] == word[now] and (ii-1,jj) not in path:
ii = ii - 1
path.append((ii, jj))
elif jj+1<lie and board[ii][jj+1] == word[now] and (ii,jj+1) not in path:
jj = jj + 1
path.append((ii, jj))
elif jj-1>-1 and board[ii][jj-1] == word[now] and (ii,jj-1) not in path:
jj = jj - 1
path.append((ii, jj))
else:
now -= 1
ok = 0
break
if ok and now == len(word)-1:
return(True)
exit()
else:
continue
return(False)
正解
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
# 为了稍后去遍历
hang = len(board) # 字母板的行数
lie = len(board[0]) # 字母板的列数
def dfs(i, j, k, visited):
if k == len(word): # 等于单词的长度则返回真,表示任务完成
return True
for x, y in [(-1, 0), (1, 0), (0, 1), (0, -1)]: # 只能向四周探寻
tmp_i = x + i
tmp_j = y + j
if 0 <= tmp_i < hang and 0 <= tmp_j < lie and (tmp_i, tmp_j) not in visited \
and board[tmp_i][tmp_j] == word[k]:
# 满足三个条件:坐标不能出界,不能重复探寻点,是否和单词当前位置k的字母相等?
visited.add((tmp_i, tmp_j)) # 是的话,探寻!!!
if dfs(tmp_i, tmp_j, k+1, visited): # 是的话,继续做同样的探寻!
return True
visited.remove((tmp_i, tmp_j)) # 这次探寻没找到,需要删掉这个点继续探寻for循环中的其他点
return False # for循环中的所有点探寻完了,没有返回真,那么就是没找到了。。。。
# 将每个字母板都作为开始字母
for i in range(hang):
for j in range(lie):
if board[i][j] == word[0] and dfs(i, j, 1, {(i, j)}):
# 因为回溯的时候不能出界,所以要(i,j),因为到达长度要停止所以要传k,最后是已经遍历过字母的集合
return(True)
exit()
return(False)
结果
总结
DFS+回溯