给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。
示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true
示例 2:
输入:board = [["a","b"],["c","d"]], word = "abcd"
输出:false
提示:
1 <= board.length <= 200
1 <= board[i].length <= 200
board 和 word 仅由大小写英文字母组成
这道题考察的是回溯法,就是一种暴力搜索,在到达某一个步骤之后,遍历这一步骤的每一个可能,如果不行就退回之前的步骤继续,,思想比较敏锐的话瞬间就可以发现这里有递归的味道了。
要用递归来解题,就要找到递归的二要素:
1. 递归参数:如果是这道题,每一个小问题就是这个点上下左右有没有符合条件的值,所以条件肯定是是这个点的坐标以及下一步要拟合的字符;
2. 终止条件/出口条件:行或者列越界,当前矩阵元素和需要匹配的元素不合,当前矩阵元素已经访问过,字符串已经全部匹配
所以这道题的递归函数应该是这个:
def dfs(i,j,k):
# 递归的出口条件:不能越界,不能不相等
if not 0 <= i <len(board) or not 0 <= j < len(board[0]) or board[i][j] != word[k]:
return False
# 出口条件2,已经全部匹配
if k == len(word) - 1:
return True
# 将已经访问过的位置元素置空,标记过已经访问
board[i][j] = ""
# 递归
res = dfs(i + 1, j, k + 1) or dfs(i - 1, j, k + 1) or dfs(i, j + 1, k + 1) or dfs(i, j - 1, k + 1)
# 返回时需要还原到初始值
board[i][j] = word[k]
return res
题目中给的二维数组大小时大于等于1的,没有特殊情况判断,所以调用这个递归函数用到两层循环就好
所以最终的解是这个:
class Solution(object):
def exist(self, board, word):
"""
:type board: List[List[str]]
:type word: str
:rtype: bool
"""
def dfs(i,j,k):
# 递归的出口条件:不能越界,不能不相等
if not 0 <= i <len(board) or not 0 <= j < len(board[0]) or board[i][j] != word[k]:
return False
# 出口条件2,已经全部匹配
if k == len(word) - 1:
return True
# 将已经访问过的位置元素置空,标记过已经访问
board[i][j] = ""
# 递归
res = dfs(i + 1, j, k + 1) or dfs(i - 1, j, k + 1) or dfs(i, j + 1, k + 1) or dfs(i, j - 1, k + 1)
# 返回时需要还原到初始值
board[i][j] = word[k]
return res
for i in range(len(board)):
for j in range(len(board[0])):
if dfs(i, j, 0):
return True
return False
作者之所以说这道题,更多的是想说明回溯法这种方法,理解之后对于相应的题目就会有相应的思路去解决,这里只是书里的第二章,后面还有更多的算法题对应这种思路。