一.引言
给定一个 m x n
二维字符网格 board
和一个字符串单词 word
。如果 word
存在于网格中,返回 true
;否则,返回 false
。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
主要有两个注意点:
A.字符串的连续性: 通过相邻的单元格字符对字符串实现拼接,所以对于一个点来说有四种选择,上下左右
B.复用性: 同一个位置的字符只能使用一次,不能重复利用
二.单词搜索
1.回溯实现
这里 Solution 类中实现了两个方法,第一个 exist 方法,负责遍历字符数组寻找目标字符串的入口,第二个方法负责从当前点的上下左右遍历,寻找是否有满足的下一个目标字符,直到返回最终状态,这里额外使用了 check_board 标记每个字符的使用状态。对应上面提到的两个点:
A.字符串的连续性:
这里采用回溯实现,当遍历数组找到目标字符的第一个字符时,即
board[i][j] == word[0] 时,函数推进至 check_exist(x, x, x, 1, x, x, x),如果找到符合 board[m][n] == word[1],继续推进 check_exist(x, x, x, 2, x, x, x),否则返回 False 并进行回退
B.复用性:
每当寻找到 board[i][j] == word[index] 时,都会将对应位置标为 False,这样推进过程中,领域中不会包含使用过的点,如果不能持续推进,则每回朔一次,都要将对应位置的状态标为 True,加入到其他推进的邻域在中
class Solution(object):
def exist(self, board, word):
"""
:type board: List[List[str]]
:type word: str
:rtype: bool
"""
# board 全部初始化为 True
check_board = [[True] * len(board[0]) for _ in range(len(board))]
# 遍历 mxn 的数字矩阵
for i in range(len(board)):
for j in range(len(board[0])):
# i,j 满足数字条件则
if board[i][j] == word[0] and check_board:
check_board[i][j] = False # 对应位置设定 False
res = self.check_exist(check_board, board, word, 1, len(word), i, j)
if res:
return True, check_board
check_board[i][j] = True
return False, check_board
# 状态矩阵 字符矩阵 目标单词 word起 word末 当前row 当前col
def check_exist(self, check_board, board, word, index, ls, row, col):
# 找到目标词 index + 1 退出条件 index = len(word)
if index == ls:
return True
# 目标单词的下一站
for temp in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
curr_row = row + temp[0]
curr_col = col + temp[1]
# 符合边界条件
if 0 <= curr_row < len(board) and 0 <= curr_col < len(board[0]):
# 不能重复使用 所以被遍历到的位置设为 False
if check_board[curr_row][curr_col] and board[curr_row][curr_col] == word[index]:
check_board[curr_row][curr_col] = False
res = self.check_exist(check_board, board, word, index + 1, len(word), curr_row, curr_col)
if res:
return res
check_board[curr_row][curr_col] = True
return False
下面是运行程序:
if __name__ == "__main__":
s = Solution()
word_board = [["A", "B", "C", "E"], ["S", "F", "C", "S"], ["A", "D", "E", "E"]]
for word_list in word_board:
print(word_list)
word = "ABCCED"
(state, board) = s.exist(board=word_board, word=word)
print(word, state)
['A', 'B', 'C', 'E']
['S', 'F', 'C', 'S']
['A', 'D', 'E', 'E']
ABCCED True
三.单词展示
数组的 index 索引与 plt 的坐标系索引不一致,所以需要完成 i,j -> plot_row,plot_col 的映射
def show(str_board, state_board):
for i in range(len(str_board)):
for j in range(len(str_board[0])):
data = str_board[i][j]
plt_row = j
plt_col = len(str_board[0]) - i
if not state_board[i][j]:
plt.scatter(plt_row, plt_col, c="black")
plt.text(plt_row, plt_col, data, fontsize=40, c='red')
else:
plt.scatter(plt_row, plt_col, c='white')
plt.text(plt_row, plt_col, data, fontsize=20)
plt.show()
show(word_board, board)
如果有兴趣也可以参考上节,将单词用线连起来。