给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]
给定 word = “ABCCED”, 返回 true
给定 word = “SEE”, 返回 true
给定 word = “ABCB”, 返回 false
提示:
board 和 word 中只包含大写和小写英文字母。
1 <= board.length <= 200
1 <= board[i].length <= 200
1 <= word.length <= 10^3
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-search
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
测试及修正过程
1.1 while 循环
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
i = 0
j = 0
k = 0
while i < len(word):
while j < len(board):
while k < len(board[j]):
if word[i] == board[j][k]:
i += 1
if j - 1 >= 0:
if word[i] == board[j - 1][k]:
j -= 1
if j + 1 < len(board):
if word[i] == board[j + 1][k]:
j += 1
if k - 1 >= 0:
if word[i] == board[j][k - 1]:
k -= 1
if k + 1 < len(board[j]):
if word[i] == board[j][k + 1]:
k += 1
else:k += 1
j += 1
if i == len(word) - 1:return True
else:return False
超出时间限制
在测试例子的时候就没有通过,于是改为 for 循环,直接控制变量递增。
1.2 for 循环
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
i = 0
j = 0
k = 0
for i in range(len(word)):
for j in range(len(board)):
for k in range(len(board[j])):
if word[i] == board[j][k]:
# 在原来基础上增设判断,测试时出现超出范围的错误
if i + 1 < len(word):
i += 1
if j - 1 >= 0:
if word[i] == board[j - 1][k]:
j -= 1
if j + 1 < len(board):
if word[i] == board[j + 1][k]:
j += 1
if k - 1 >= 0:
if word[i] == board[j][k - 1]:
k -= 1
if k + 1 < len(board[j]):
if word[i] == board[j][k + 1]:
k += 1
if i == len(word) - 1:return True
else:return False
解答错误
官方情况
对每一个位置 (i,j) 都调用函数 check(i,j,0) 进行检查:只要有一处返回 true,就说明网格中能够找到相应的单词,否则说明不能找到。
为了防止重复遍历相同的位置,需要额外维护一个与 board 等大的 visited 数组,用于标识每个位置是否被访问过。每次遍历相邻位置时,需要跳过已经被访问的位置。
from typing import List
class Solution:
# (x-1,y)
# (x,y-1) (x,y) (x,y+1)
# (x+1,y)
directions = [(0, -1), (-1, 0), (0, 1), (1, 0)]
def exist(self, board: List[List[str]], word: str) -> bool:
m = len(board)
if m == 0:
return False
n = len(board[0])
marked = [[False for _ in range(n)] for _ in range(m)]
for i in range(m):
for j in range(n):
# 对每一个格子都从头开始搜索
if self.__search_word(board, word, 0, i, j, marked, m, n):
return True
return False
def __search_word(self, board, word, index,
start_x, start_y, marked, m, n):
# 先写递归终止条件
if index == len(word) - 1:
return board[start_x][start_y] == word[index]
# 中间匹配了,再继续搜索
if board[start_x][start_y] == word[index]:
# 先占住这个位置,搜索不成功的话,要释放掉
marked[start_x][start_y] = True
for direction in self.directions:
new_x = start_x + direction[0]
new_y = start_y + direction[1]
# 注意:如果这一次 search word 成功的话,就返回
if 0 <= new_x < m and 0 <= new_y < n and \
not marked[new_x][new_y] and \
self.__search_word(board, word,
index + 1,
new_x, new_y,
marked, m, n):
return True
marked[start_x][start_y] = False
return False
#https://leetcode-cn.com/problems/word-search/solution/zai-er-wei-ping-mian-shang-shi-yong-hui-su-fa-pyth/
官方解
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
def check(i: int, j: int, k: int) -> bool:
if board[i][j] != word[k]:
return False
if k == len(word) - 1:
return True
visited.add((i, j))
result = False
for di, dj in directions:
newi, newj = i + di, j + dj
if 0 <= newi < len(board) and 0 <= newj < len(board[0]):
if (newi, newj) not in visited:
if check(newi, newj, k + 1):
result = True
break
visited.remove((i, j))
return result
h, w = len(board), len(board[0])
visited = set()
for i in range(h):
for j in range(w):
if check(i, j, 0):
return True
return False
#https://leetcode-cn.com/problems/word-search/solution/dan-ci-sou-suo-by-leetcode-solution/