题目难度: 中等
原题链接
今天继续更新剑指 offer 系列, 这道题用到了经典的图算法, 而且时间和空间上都有一些可以优化的地方, 质量不错
老样子晚上 6 点 45 分准时跟大家见面, 大家在我的公众号"每日精选算法题"中的聊天框中回复 offer 就能看到剑指 offer 系列当前连载的所有文章了
大家有什么想法建议和反馈的话欢迎随时交流, 包括但不限于公众号聊天框/知乎私信评论等等~
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的 3×4 的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。
[[“a”,“b”,“c”,“e”],
[“s”,“f”,“c”,“s”],
[“a”,“d”,“e”,“e”]]
但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符 b 占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCCED”
true
board = [[“a”,“b”],[“c”,“d”]], word = “abcd”
false
O((3^L)*RC)
O(3^L)
O(RC)
O((3^L)*RC)
O(L)
O(L)
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
# DFS + 回溯
# 针对每一个首字符, 找所有可能的字符串, 剪枝
rows, cols = len(board), len(board[0])
def dfs(r, c, i):
# i表示当前的目标字符串下标
if i == len(word):
# 如果已经遍历完整个目标字符串, 则说明找到一条有效路径, 直接返回True
return True
# 4个方向遍历 (注意实际只会有3个方向继续下去, 因为上一个节点已经被访问过, 不会再访问它)
for (rr, cc) in ((r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)):
if 0 <= rr < rows and 0 <= cc < cols and board[rr][cc] == word[i]:
# 优化1: 将visit集合优化为直接标记原矩阵, 节省空间
# 注意上面不需要再判断board[rr][cc]是否是None (是否被访问过), 因为如果是None的话肯定不可能等于word[i]
cur, board[rr][cc] = board[rr][cc], None
if dfs(rr, cc, i + 1):
# 优化2: 剪枝, 找到一条路径直接返回True, 节省时间
return True
board[rr][cc] = cur
return False
for r in range(rows):
for c in range(cols):
if board[r][c] == word[0]:
# 只有当前字符与目标字符串开头相同时才开始DFS, 其他字符开头就不相同
# 注意需要先将起始字符标记成访问过, 避免重复再访问它
cur, board[r][c] = board[r][c], None
if dfs(r, c, 1):
return True
board[r][c] = cur
# 没找到有效路径, 返回False
return False
大家可以在下面这些地方找到我~
我的知乎专栏
我的 CSDN
我的 Leetcode
我的牛客网博客
我的公众号: 每日精选算法题, 欢迎大家扫码关注~